이번 포스팅에서는

 

(1) pandas.Series.explode() 메소드를 사용해서  Series 안의 리스트를 행으로 변환하기 

(2) pandas.Series.explode() 메소드를 사용해서 DataFrame 안의 리스트를 행으로 변환하기

(3) DataFrame의 float 자리수를 지정해주기

 

방법을 소개하겠습니다. 

 

 

 

 

 

(1) pandas.Series.explode() 메소드를 사용해서  Series 안의 리스트(list)를 행으로 변환하기

 

ignore_index=False 가 디폴트 모드이며, 같은 리스트 내 원소들에 대해서는 같은 인덱스 번호가 부여됩니다. 

 

import pandas as pd

# Series.explode(ignore_index=False)
# Transform each element of a list-like to a row.

s = pd.Series([[4, 9, 6, 1, 8], 'love', [], [3, 0, 1]])

## # by default: ignore_index=False
s.explode(ignore_index=False)

# 0       4
# 0       9
# 0       6
# 0       1
# 0       8
# 1    love
# 2     NaN
# 3       3
# 3       0
# 3       1
# dtype: object

 

 

ignore_index=True 로 설정을 해주면 0, 1, ..., n-1 의 순서대로 인덱스 번호가 부여됩니다. 

 

## If 'ignore_index=True', the resulting index will be labeled 0, 1, …, n - 1.
s.explode(ignore_index=True)

# 0       4
# 1       9
# 2       6
# 3       1
# 4       8
# 5    love
# 6     NaN
# 7       3
# 8       0
# 9       1
# dtype: object

 

 

 

(2) pandas.Series.explode() 메소드를 사용해서 DataFrame 안의 리스트를 행으로 변환하기

 

먼저, 리스트를 원소로 가지는 pandas DataFrame을 예시로 만들어보겠습니다. 바로 이어서 리스트를 풀어서 각 행으로 변환할 것이므로 각 열별 리스트 내 원소의 개수가 서로 같아야 합니다. 

 

## DataFrame with lists
df = pd.DataFrame({
    'grp': [['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c']], 
    'id': [[1, 2, 3, 4, 5, 6, 7, 8, 9]], 
    'value': [[0.0, 0.421948, 0.9422, 0.582, 0.0, 0.28574, 0.55382, 0.2801, 0.87]]
})

print(df)
#                       grp \
# [a, a, a, b, b, b, c, c, c]  
#
#                       id  \
# [1, 2, 3, 4, 5, 6, 7, 8, 9]   
#                                                               value  
# [0.0, 0.421948, 0.9422, 0.582, 0.0, 0.28574, 0.55382, 0.2801, 0.87]]

 

 

위의 (1)번에서 소개했던 pandas.Series.explode() 메소드를 apply() 함수를 사용해서 위에서 만든 DataFrame df 의 모든 열에 적용해줍니다. 옆으로 길게 리스트 형태로 있던 DataFrame 내 원소가 각 행(row)의 개별 원소로 풀어져서 세로로 긴 DataFrame 형태로 변형되었습니다. 

 

## unpacking the lists in DataFrame
df_unpacked = df.apply(pd.Series.explode)

print(df_unpacked)
#   grp id     value
# 0   a  1       0.0
# 0   a  2  0.421948
# 0   a  3    0.9422
# 0   b  4     0.582
# 0   b  5       0.0
# 0   b  6   0.28574
# 0   c  7   0.55382
# 0   c  8    0.2801
# 0   c  9      0.87

 

 

 

(3) DataFrame의 float 자리수를 지정해주기

 

세번째 칼럼인 'value'의 float 값들의 자리수가 서로 달라서 보기에 좋지 않습니다. 이럴 경우 astype(float).round(2) 메소드를 사용해서 소수점 2째 자리로 반올일해서 자리수를 일치시켜주면 보기에 깔끔하고 좋습니다. 

 

## Output to two decimal places
df_unpacked['value'] = df_unpacked['value'].astype(float).round(2)

print(df_unpacked)
#   grp id  value
# 0   a  1   0.00
# 0   a  2   0.42
# 0   a  3   0.94
# 0   b  4   0.58
# 0   b  5   0.00
# 0   b  6   0.29
# 0   c  7   0.55
# 0   c  8   0.28
# 0   c  9   0.87

 

 

[ Reference ]

* pandas.Series.explode() 메소드

   : https://pandas.pydata.org/docs/reference/api/pandas.Series.explode.html

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 리스트와 사전 자료형을 이용해서 문자열과 숫자를 서로 매핑하고 변환하는 방법을 소개하겠습니다. 

(예전에 이와 비슷한 포스팅을 한적이 있는데요, 예전 거에서 한 발자국씩만 더 나가봤습니다.)

 

(1) 리스트 내 문자열을 숫자로 변환하기

(2) 리스트 내 숫자를 문자열로 변환하기

(3) 고유한 문자열에 정수를 매핑하기 

(4) 고유한 정수에 문자열을 매핑하기 

 

 

 

(1) 리스트 내 문자열 을 숫자로 변환하기

 

* 방법 1: Python의 List Comprehensionint(str) 메소드를 같이 사용하는 방법입니다. 

 

## Converting string list to integer list

str_list = ['5', '12', '8', '19', '34']

## way 1: list comprehension
int_list = [int(x) for x in str_list]

print(int_list)
# [5, 12, 8, 19, 34]

 

 

* 방법 2: map() 메소드를 사용해서 list(map(int, string_list)) 형태로 사용하는 방법입니다. 

 

## way 2: map(int, str) function
int_list2 = list(map(int, str_list))

print(int_list2)
# [5, 12, 8, 19, 34]

 

 



(2) 리스트 내 문자열을 숫자로 변환하기

 

리스트 안의 문자열을 숫자로 바꾸는 방법은 위의 (1)번에서 소개한 2가지 방법과 동일하며, int() 대신 str()을 사용해주면 됩니다. 

 

## converting integer to string

## way 1: list comprehension
[str(i) for i in int_list]
# ['5', '12', '8', '19', '34']


## way 2: map(str, int_list)
list(map(str, int_list))
# ['5', '12', '8', '19', '34']

 

 

 

(3) 고유한 문자열에 정수를 매핑하기 

 

(3-1) sorted(set(label_list)) : 먼저 문자열 리스트 에서 유일한(unique) 문자열 집합을 추출해서 정렬한 후에 

          --> {k: v+1 for v, k in enumerate(sorted(set(label_list)))} 
                : 유일한 문자열 별로 1부터 순차적으로 정수를 부여한 사전 자료형을 만듭니다 (향후 매핑 참조에 사용됨)

 

## original label list
label_list = ['cat', 'dog', 'cat', 'car', 'tree', 'tree', 'dog']

sorted(set(label_list))
# ['car', 'cat', 'dog', 'tree']


## mapping index dictionary(label key: integer value)
label_int_dict = {
    k: v+1 for v, k in enumerate(
        sorted(set(label_list))
    )
}


print(label_int_dict)
# {'car': 1, 'cat': 2, 'dog': 3, 'tree': 4}

 

 

(3-2) for x in label_list : label_list 에서 순서대로 문자열 원소값을 for loop 순환문을 통해 하나씩 가져와서 

          --> [label_int_dict[x]] : 위의 (3-1)에서 생성한 매핑 사전에서 문자열에 해당하는 정수를 매핑해주고 리스트로 만들어줍니다. 

 

## mapping label to integer index using list comprehension
mapped_int_list = [label_int_dict[x] for x in label_list]

print(mapped_int_list)
# [2, 3, 2, 1, 4, 4, 3]

 

 

 

(4) 고유한 정수에 문자열을 매핑하기 

 

(4-1) for k, v in label_int_dict.items() : 위의 (3-1)에서 생성한 문자열-정수 매핑 사전에서 Key, Value 를 불러와서 

          --> {v: k} : {Value: Key} 로 서로 키와 값의 위치를 바꾸어서 새로 사전 자료형을 만들어줍니다. 

                             (아래 (4-2)에서 매핑 사전으로 사용됨) 

 

## converting integer to label string
int_label_dict = {
    v: k for k, v in label_int_dict.items()
}

print(int_label_dict)
# {1: 'car', 2: 'cat', 3: 'dog', 4: 'tree'}

 

 

(4-2) for x in mapped_int_list : 위의 (3-2)에서 변환했던 mapped_int_list 리스트에서 정수를 하나씩 불러와서 

          --> [int_label_dict[x]] : (4-1)에서 생성한 {정수: 문자열} 매핑 사전을 이용해서 정수에 해당하는 문자열을 매핑하고 리스트로 만들어줍니다. 

 

## mapping integer to label using list comprehension
mapped_label_list = [int_label_dict[x] for x in mapped_int_list]

print(mapped_label_list)
# ['cat', 'dog', 'cat', 'car', 'tree', 'tree', 'dog']

 

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 Python의 Plotly 모듈을 이용해서 클리브랜드 점 그래프 (Cleveland Dot Plot in Python using Plotly) 그리는 방법을 소개하겠습니다. 

 

Cleveland and McGill (1984) 이  “Graphical Methods for Data Presentation: Full Scale Breaks, Dot Charts, and Multibased Logging.” 이라는 논문에서 막대 그래프 대비 점 그래프가 데이터 해석, 가독성에서 가지는 우수성을 소개하면서 Cleveland Dot Plot 이라고도 많이 불리는 그래프입니다.

 

예제로 사용할 데이터로, "학교(schools)" 범주형 변수의 졸업생 별 남성(men)과 여성(women)의 수입(earning) 데이터로 pandas DataFrame을 만들어보겠습니다. 

 

## making a sample pandas DataFrame
import pandas as pd

df = pd.DataFrame({
    'schools': [
        "Brown", "NYU", "Notre Dame", "Cornell", "Tufts", "Yale",
        "Dartmouth", "Chicago", "Columbia", "Duke", "Georgetown",
        "Princeton", "U.Penn", "Stanford", "MIT", "Harvard"],
    'earnings_men': [
        92, 94, 100, 107, 112, 114, 114, 118, 119, 124, 131, 137, 141, 151, 152, 165], 
    'earnings_women': [
        72, 67, 73, 80, 76, 79, 84, 78, 86, 93, 94, 90, 92, 96, 94, 112]
})



print(df)
#        schools  earnings_men  earnings_women
# 0        Brown            92              72
# 1          NYU            94              67
# 2   Notre Dame           100              73
# 3      Cornell           107              80
# 4        Tufts           112              76
# 5         Yale           114              79
# 6    Dartmouth           114              84
# 7      Chicago           118              78
# 8     Columbia           119              86
# 9         Duke           124              93
# 10  Georgetown           131              94
# 11   Princeton           137              90
# 12      U.Penn           141              92
# 13    Stanford           151              96
# 14         MIT           152              94

# 15     Harvard           165             112

 

 

Plotly 의 graph_objects 메소드를 사용해서 졸업한 학교(schools) 별 남성의 수입(earnings_men)과 여성의 수입(earnings_women) 에 대해서 점으로 마킹을 하고 수입을 텍스트로 표기 (mode="markers + text") 하여 클리브랜드 점 그래프 (Cleveland Dot Plot)을 그려보겠습니다. 

 

import plotly.graph_objects as go

fig = go.Figure()

## Dot Plot for Men
fig.add_trace(go.Scatter(
    x=df['earnings_men'],
    y=df['schools'],
    marker=dict(color="red", size=10),
    mode="markers + text",
    name="Men",
    text=df['earnings_men'],
    textposition="middle right"
))

## Dot Plot for Women
fig.add_trace(go.Scatter(
    x=df['earnings_women'],
    y=df['schools'],
    marker=dict(color="blue", size=10),
    mode="markers + text",
    name="Women",
    text=df['earnings_women'],
    textposition="middle left"
))

## title and axis title
fig.update_layout(
    title="Earnings by School and Gender",
    xaxis_title="Annual Salary (in thousands)",
    yaxis_title="School")


fig.show()

Cleveland Dot Plot in Python using Plotly

 

Plotly 그래프는 interactive mode 로서 마우스 커서를 그래프에 가져다대면 해당 점의 정보가 팝업으로 나타나서 편리하게 볼 수 있습니다. 

 

R의 ggplot2 패키지를 이용한 클리브랜드 점 그래프 (Cleveland Dot Plot in R using ggplot2) 그리는 방법은 https://rfriend.tistory.com/75 를 참고하세요. 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 Python 의 Plotly 모듈을 사용해서 

 

(1) 3차원 산점도 그리기 (3D Scatter Plot using Plotly)

(2) 3차원 표면도 그리기 (3D Surface Plot using Plotly) 

 

하는 방법을 소개하겠습니다 

 

 

 

(1) 3차원 산점도 그리기 (3D Scatter Plot using Plotly)

 

3차원 산점도는 x, y, z 의 3개 축을 기준으로 3차원의 공간에 산점도를 그려서 3개 변수들 간의 관계를 분석하기 위해서 사용합니다. 마커의 크기와 색깔을 달리해서 4번째 변수의 특성을 3차원 산점도에 추가해서 그릴 수도 있습니다. 

 

Scatter3D trace 는 go.Scatter3D() 함수에 의해 반환되는 그래프 객체입니다. 3차원 산점도이기 때문에 x, y, z 의 좌표값을 반드시 넣어줘야 하며, 이들 값은 리스트(List) 또는 Array 객체를 사용합니다. 

 

아래는 싸인과 코싸인 값을 이용해서 3차원 산점도를 그려본 예입니다. 

 

import plotly.graph_objs as go
import numpy as np

z = np.linspace(0, 10, 50)
x = np.cos(z)
y = np.sin(z)

trace = go.Scatter3d(
   x = x, 
   y = y, 
   z = z,
   mode = 'markers', 
   marker = dict(
      size = 12,
      color = z, 
      colorscale = 'Bluered_r'
      )
   )

layout = go.Layout(title = '3차원 산점도 (3D Scatter plot)')

fig = go.Figure(data = [trace], layout = layout)

fig.show()

3D Scatter Plot in Python using Plotly

 

 

 

(2) 3차원 표면도 그리기 (3D Surface Plot using Plotly) 

 

3차원 표면도는 위도(x, latitude), 경도(y, longitude), 고도(z, altitude) 의 3차원 데이터를 그래프로 표현한 것입니다. 이때 3차원 데이터 값을 개별 점(indivisual points)으로 표현한 대신에 표면(surface)으로 표현하여서 3차원 데이터 간의 관계를 분석할 때 사용합니다.

 

이때 위도(x, latitude), 경도(y, longitude)는 독립변수(indepedent variable)이 되고, 고도(z, altitude)는 종속변수(dependent variable) 가 됩니다. 

 

아래 예는 Plotly의 graph_objs 메소드 중에서 go.Surface() 메소드를 사용해서 3차원 표면도를 그려면 것입니다. 

 

import numpy as np
import plotly.graph_objs as go

x = np.outer(np.linspace(-2, 2, 30), np.ones(30))
y = x.copy().T # transpose
z = np.cos(x ** 2 + y ** 2)

trace = go.Surface(x = x, y = y, z =z )
data = [trace]

layout = go.Layout(title = '3차원 표면도 (3D Surface Plot)')

fig = go.Figure(data = data, layout=layout)

fig.show()

 

 

Plotly 그래프는 interactive mode 를 지원하기 때문에 마우스 커서를 그래프 위에 가져가면 해당 좌표의 정보가 팝업으로 나타납니다. 그리고 커서를 클릭해서 위-아래-좌-우 방향으로 이동하면 3차원 표면도가 방향이 돌아가기 때문에 입체적으로 3차원 표면을 관찰할 수 있는 장점이 있습니다. 

 

 

[Reference]

* Plotly - 3D Scatter and Surface Plot
 : https://www.tutorialspoint.com/plotly/plotly_3d_scatter_and_surface_plot.htm

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다 .

행복한 데이터 과학자 되세요!  :-)

 

 

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 Python 의 Pandas 에서 함수를 적용할 때 사용하는 map(), applymap(), apply() 메소드에 대해서 알아보겠습니다. 

 

(1) map(): Series 에 대해 element-wise 로 함수 적용

(2) applymap(): DataFrame에 대해 element-wise 로 함수 적용

(3) apply(): DataFrame에 대해 행/열 (row/column) 로 함수 적용

 

 

Pandas 함수 적용하기: map, applymap, apply

 

 

(1) map(): Series 에 대해 element-wise 로 함수 적용

 

예제로 사용할 DataFrame을 만들어보겠습니다. 

 

import numpy as np
import pandas as pd

## making a sample pandas DataFrame
np.random.seed(1004)

df = pd.DataFrame(
    np.random.randn(4, 3), 
    columns=['x1', 'x2', 'x3'], 
    index=['A', 'B', 'C', 'D'])

print(df)
#          x1        x2        x3
# A  0.594403  0.402609 -0.805162
# B  0.115126 -0.753065 -0.784118
# C  1.461576  1.576076 -0.171318
# D -0.914482  0.860139  0.358802

 

 

 

map() 메소드는 pandas Series 에 대해 함수를 적용할 때 사용합니다. 아래 예제는 익명 함수 lambda 로 정의한 s_formater 함수를 map() 메소드로 Series에 적용해 본 것입니다. 

 

## pandas Series
df['x1']
# A    0.594403
# B    0.115126
# C    1.461576
# D   -0.914482
# Name: x1, dtype: float64


## map: applying an element-wise function for Series
s_formater = lambda x: '%.2f'% x

df['x1'].map(s_formater)
# A     0.59
# B     0.12
# C     1.46
# D    -0.91
# Name: x1, dtype: object

 

 

 

아래 예제에서는 Series의 인덱스를 키로 해서 매핑(mapping by index)하여 Series의 값을 변환한 것입니다. 

-------------------------------------------------------

s_1 인덱스 --> s_1 값 = s_2 인덱스  -->  s_2 값

-------------------------------------------------------

'a'             -->             0                    -->     'A'

'b'             -->             1                     -->     'B'

'c'             -->             2                     -->     'C'

-------------------------------------------------------

 

 

## 예제 pandas Series 만들기
s_1 = pd.Series({'a': 0, 'b': 1, 'c': 2})
s_2 = pd.Series({0: 'A', 1: 'B', 2: 'C'})

print(s_1)
# a    0
# b    1
# c    2
# dtype: int64

print(s_2)
# 0    A
# 1    B
# 2    C
# dtype: object


##-- 인덱스 키를 기준으로 매핑하기 (mapping by index on Series)
print(s_1.map(s_2))
# a    A
# b    B
# c    C
# dtype: object

 

 

 

(2) applymap(): DataFrame에 대해 element-wise 로 함수 적용

 

다음 예제는 applymap() 메소드를 사용해서 익명함수 lambda 로 정의한 s_formater 함수를 DataFrame 의 각 원소에 대해 적용한 것입니다. (map() 은 Series 대상 vs. applymap()은 DataFrame 대상 element-wise 함수 적용)

 

## applymap: applying an element-wise for DataFrame
s_formater = lambda x: '%.2f'% x

df_2 = df.applymap(s_formater)

print(df_2)
#       x1     x2     x3
# A   0.59   0.40  -0.81
# B   0.12  -0.75  -0.78
# C   1.46   1.58  -0.17
# D  -0.91   0.86   0.36

 

 

 

(3) apply(): DataFrame에 대해 행/열 (row/column) 로 함수 적용

 

아래 예제는 column 기준 (axis=0),  row 기준 (axis=1) 으로 익명함수 lambda로 정의한 (열 또는 행 기준, 최대값 - 최소값) 을 계산하는 함수를 apply() 메소드로 DataFrame에 대해 적용해본 것입니다. 

 

## apply: applying a function on row/column basis of a DataFrame
f = lambda x: x.max() - x.min()

## on column basis
df.apply(f, axis=0)

# x1    2.376058
# x2    2.329141
# x3    1.163964
# dtype: float64



## on row basis
df.apply(f, axis=1)

# A    1.399565
# B    0.899243
# C    1.747393
# D    1.774621
# dtype: float64

 

 

 

아래 예는 apply() 메소드를 써서 DataFrame에 행(row) 기준으로 최대값을 계산하는 익명함수 lambda로 정의한 함수를 적용해서 'x_max'라는 새로운 칼럼을 추가한 것입니다. 

 

## 새로운 칼럼 추가하기
df['x_max'] = df.apply(lambda x: x.max(), axis=1)

print(df)
#          x1        x2        x3     x_max
# A  0.594403  0.402609 -0.805162  0.594403
# B  0.115126 -0.753065 -0.784118  0.115126
# C  1.461576  1.576076 -0.171318  1.576076
# D -0.914482  0.860139  0.358802  0.860139


## equivalent
df['x_max'] = df.max(axis=1)

 

 

* Pandas DataFrame에서 여러개의 칼럼에 대해 그룹을 집계를 할 때 다른 집계 함수를 적용하는 방법은 https://rfriend.tistory.com/393 를 참고하세요. 

 

* Python의 익명 함수 lambda 에 대해서는 https://rfriend.tistory.com/366 를 참고하세요. 

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 Python의 List Comprehension 에 대해서 알아보겠습니다.

(번역하기가 애매해서 영어 원문 그대로 사용하겠습니다)

 

1. List Comprehension 이란? 

 

Python의 List Comprehension 은 기존에 존재하는 List 에서 새로운 List 를 간결하게 생성하는 방법입니다.

 

List Comprehension Syntax 는 아래와 같습니다. 

new_list = [expression for item in iterable if condition == True]

 

 

 

간단한 예를 들어서 설명해보겠습니다.  아래에 6개의 도시를 원소로 가지는 List 가 있습니다. 첫글자가 "S"로 시작하는 도시명을 원소로 가지는 새로운 List를 만든다고 했을 때, for loop 순환문과 if 조건절을 사용하는 방법이 있습니다. 

 

city_list = ["Seoul", "New York", "London", "Shanghai", "Paris", "Tokyo"]

print(city_list)
# ['Seoul', 'New York', 'London', 'Shanghai', 'Paris', 'Tokyo']


## way 1: for loop and if conditional statement
city_s_1 = []

for city in city_list:
    if "S" in city:
        city_s_1.append(city)
        
        
print(city_s_1)
# ['Seoul', 'Shanghai']

 

 

첫글자가 "S"로 시작하는 도시명을 원소로 가지는 새로운 List를 만든다고 했을 때, List Comprehension 을 이용하면 아래와 같이 아주 간결하게 코드를 짤 수 있습니다. 

 

## way 2: List Comprehension
## [expression for item in iterable if condition == True]
city_s_2 = [city for city in city_list if "S" in city]

print(city_s_2)
# ['Seoul', 'Shanghai']

 

 

 

2. 내장 range() 함수와 조건절을 사용한 List Comprehension

 

Python의 iterable 자료형으로 str, list, tuple, dictionary, set, range 등이 있는데요, 아래 예에서는 그중에서 내장 range() 함수로 0~9까지의 정수를 반복적으로 생성해서, if 조건절을 사용해 짝수로 구성된 새로운 List 를 만들어보겠습니다. 

 

## range() 함수와 List Comprehension 으로 짝수 리스트 만들기
even_list = [i for i in range(10) if i%2 == 0]

print(even_list)
# [0, 2, 4, 6, 8]

 

 

 

3. if else 조건절을 사용해서 List Comprehension 만들기

 

if else 조건절을 List Comprehension 에서 사용할 때는 if else 조건절을 앞에 써주고, for loop 순환문을 뒤에 사용해줍니다. (* 위의 2번과 순서가 뒤바뀜에 주의)

 

## 짝수는 그대로, 홀수이면 99로 치환한 리스트
## if else 조건절이 앞에 있고, for 순환문이 뒤에 있음
if_else_list = [i if i%2 == 0 else 99 for i in range(10)]

print(if_else_list)
# [0, 99, 2, 99, 4, 99, 6, 99, 8, 99]

 

 

만약 for loop 순환문을 앞에 써주고 if else 조건절을 뒤에 써서 List Comprehension 을 시도하면 SyntaxError 가 납니다. 

 

## SyntaxError: invalid syntax
[i for i in range(10) if i%2 == 0 else 99] #SyntaxError

 

 

 

4. 2D List 에 대해 중첩된 순환문(Nested for loops)을 사용해서 List Comprehension 

 

4-1.  2D List 를 1D List 로 차원 줄이기 (flattening)

 

list_2d = [[11, 12], 
           [21, 22], 
           [31, 32], 
           [41, 42]
          ]
          
print(list_2d)
# [[11, 12], [21, 22], [31, 32], [41, 42]]


## flattening
## flattening
list_1d = [i for row in list_2d for i in row]

print(list_1d)
# [11, 12, 21, 22, 31, 32, 41, 42]

 

 

4-2. 2D List 를 전치(Transpose) 하기 

 

## Transpose
list_transpose = [[row[i] for row in list_2d] for i in range(2)]

print(list_transpose)
# [[11, 21, 31, 41], [12, 22, 32, 42]]

 

 

 

5. eval() 함수에 List Comprehension 실행하기

 

Python의 eval() 함수는 동적으로 문자열 표현식을 평가하여 실행합니다. (참고: https://rfriend.tistory.com/798 )

eval() 함수에 List Comprehension 을 문자열 표현식으로 넣어서 실행할 수 있습니다. 

 

## eval() 에 list comprehension 표현식(expression)사용 가능
str_list_comprehension = "[i for i in range(10) if i%2 == 0]"

eval(str_list_comprehension)
# [0, 2, 4, 6, 8]

 

 

하지만, 바로 위의 짝수 리스트를 만드는 List Comprehension 과 동일한 과업을 for loop 순환문과 if 조건절 statement 를 문자열로 만들어서 eval() 함수에 넣어 실행하려고 하면 SyntaxError 가 발생합니다. (eval() 함수는 expression 만 평가하여 실행가능하고, statement 는 평가 불가능함)

 

## eval()에 for loop 순환문과 if 조건절 statement 사용 불가
## SyntaxError: invalid syntax
str_for_if = """
new_list = []

for i in range(10):
    if i%2 == 0:
        new_list.append(i)
"""

eval(str_for_if) # SyntaxError: invalid syntax

 

 

 

6. List Comprehension 으로 새로운 Dict 만들기

 

str 자료형은 iterable 타입으로서, 아래처럼 List Comprehension 으로 각 단위문자 별로 쪼개서 새로운 List 로 만들 수 있습니다.  

 

text = "abcde"

print([s for s in text])
# ['a', 'b', 'c', 'd', 'e']

 

 

아래의 예는 range() 함수와 text 를 iterable 하면서 zip() 으로 정수와 각 단위문자를 짝을 이루어서 for loop 순환문으로 발생시키고, 이를  {Key: Value} 로 해서 새로운 Dict 자료형을 만든 것입니다.  

 

## list comprehension을 이용해서 dictionary 만들기
text = "abcde"

{k: v for k, v in zip(range(len(text)), text)}
# {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e'}

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,

이번 포스티에서는 Python의 내장 함수인 eval() 함수에 대해서 소개하겠습니다. 

 

(1) Python의 eval() 함수 구문 이해 및 문자열 표현식 인풋을 eval() 함수에 사용하기

(2) eval() 함수의 잘못된 사용 예시 (SyntaxError) 

(3) compiled-code-based 인풋을 eval() 함수에 사용하기

 

 

python eval() function

 

(1) Python의 eval() 함수 구문 이해 및 문자열 표현식 인풋을 eval() 함수에 사용하기

 

Python 의 내장함수(built-in function)인 eval() 함수는 임의의 문자열 기반(string-based) 또는 컴파일된 코드 기반 (compiled-code-based) 인풋의 표현식(expressions)을 평가(evaluate)해서 실행해줍니다. 

 

문자열 기반의 표현식을 eval() 함수가 처리하는 순서는 아래와 같습니다. 

 

  (1-a) 문자열 기반 표현식을 파싱한다. (Parse a string-based expression)

  (1-b) 문자열을 파싱한 결과를 바이트코드로 컴파일한다. (Compile it to bytecode)

  (1-c) 파이썬 표현식으로 평가한다. (Evaluate it as a Python expression) 

  (1-d) 평가한 결과를 하나의 값으로 반환한다. (Return the result of the evaluation)

 

 

아래 예시는 문자열 기반 표현식 (string-based expressions) 으로 수학 계산식(math expressions)을 인풋으로 해서 eval() 메소드를 사용해 동적으로 평가하여 실행한 것입니다. 

 

## You can use the built-in Python eval() 
## to dynamically evaluate expressions 
## from a string-based or compiled-code-based input.

##-- eval() for a string-based input
##-- Math expressions
eval("2 + 6")
# 8

eval("10**2")
# 100

eval("sum([1, 2, 3, 4, 5])")
# 15


import math
eval("math.pi * pow(5, 2)")
# 78.53981633974483

 

 

 

eval() 함수는 문자열 표현식에서 아래 예의 x 와 같은 글로벌 변수에 접근해서 표현식을 평가하고 실행할 수 있습니다.  

 

## eval() has access to global names like x
x = 10
eval("x * 5")
# 50

 

 

 

eval() 함수는 문자열의 블리언 표현식 (Boolean expressions)에 대해서도 평가하여 실행할 수 있습니다.

 

아래의 예에서는 순서대로 블리언 표현식 (Boolean expressions)의 

  (a) 비교 연산자 (value comparison operstors: <, >, <=, >=, ==, !=)),

  (b) 논리 연산자 (logical operators: and, or, not),

  (c) 소속 여부 확인 연산자 (membership test operators: in, not in),

  (d) 동일 여부 확인 연산자 (identity operators: is, is not)

을 사용한 문자열 기반 인풋을 eval() 메소드를 통해 평가하고 실행해 보았습니다. 

 

## -- eval() for Boolean expressions
x = 10

## (a) value comparison operators: <, >, <=, >=, ==, !=
eval("x > 5")
# True


## (b) logical operstors: and, or, not
eval("x > 5 and x < 9")
# False


## (c) membership test operators: in, not in
eval("x in {1, 5, 10}")
# True


## (d) identity operators: is, is not
eval("x is 10")
# True

 

 

 

그러면, 그냥 Python 표현식을 쓰면 되지, 왜 굳이 문자열 기반의 표현식을 eval() 함수에 인풋으로 넣어서 쓸까 궁금할 것입니다. 아래의 조건 표현식을 가지는 사용자 정의 함수를 예로 들자면, 사용자 정의함수 myfunc() 를 사용할 때처럼 동적으로 문자열 기반의 조건절 표현식을 바꾸어가면서 쓸 수 있어서 강력하고 편리합니다. 

 

## suppose you need to implement a conditional statement, 
## but you want to change the condition on the fly, dynamically. 
def myfunc(a, b, condition):
    if eval(condition):
        return a + b
    return a - b
    
    
myfunc(5, 10, "a > b")
# -5


myfunc(5, 10, "a <= b")
# 15


myfunc(5, 10, "a is b")
# -5

 

 

 

(2) eval() 함수의 잘못된 사용 예시 (SyntaxError) 

 

(2-1) 만약 eval() 함수의 인풋으로 표현식(expressions) 이 아니라, if, while 또는 for 와 같은 키워드를 사용해서 만든 코드 블락으로 이루어진 명령문(statement)을 사용한다면 "SyntaxError: invalid syntax" 에러가 발생합니다. 

 

## if you pass a compound statement to eval(), 
## then you'll get a SyntaxError. 
x = 10
eval("if x>5: print(x)")
# File "<string>", line 1
#     if x>5: print(x)
#     ^
# SyntaxError: invalid syntax

 

 

 

(2-2) eval() 함수에 할당 연산(assignment operations: =) 을 사용하면 "SyntaxError: invalid syntax" 에러가 발생합니다. 

 

## Assignment operations aren't allowed with eval(). 
eval("x = 10")
# File "<string>", line 1
#     x = 10
#       ^
# SyntaxError: invalid syntax

 

 

 

(2-3) Python 구문의 규칙을 위배하면 "SyntaxError: unexpedted EOF while parsing" 에러가 발생합니다. 

(아래 예에서는 "1 + 2 -" 에서 문자열 마지막에 - 부호가 잘못 들어갔음) 

 

## If an expression violates Python syntax, then SyntaxError
eval("1 + 2 -")
# File "<string>", line 1
#     1 + 2 -
#           ^
# SyntaxError: unexpected EOF while parsing

 

 

 

(3) compiled-code-based 인풋을 eval() 함수에 사용하기

 

eval() 함수의 인풋으로 위의 문자열 기반 객체 대신 compiled-code-based 객체를 사용할 수도 있습니다. compiled-code-based 객체를 eval() 함수의 인풋으로 사용하면 아래의 두 단계를 거칩니다. 

 

  (3-a) 컴파일된 코드를 평가한다. (Evaluate the compiled code)

  (3-b) 평가 결과를 반환한다. (Return the result of the evaluation)

 

위의 (1)번에서 문자열 기반의 표현식을 eval() 함수의 인풋으로 사용했을 때 대비 compiled-code 객체를 eval() 함수의 인풋으로 사용할 경우 파싱하고 컴파일 하는 단계가 없고, 바로 컴파일된 코드를 평가하고 반환하는 단계로 넘어가므로 똑같은 표현식을 여러번 평가해야 하는 경우에 속도 향상을 기대할 수 있습니다. 

 

 

Python의 eval() 함수에 compiled code 객체를 인풋으로 사용하려면, 

compiled_code_object = compile(source, filename, mode) 의 구문을 사용해서 컴파일 해주면 됩니다. 

 - source 에는 문자열 표현식(string-based expression)을 넣어줍니다. 

 - filename 에는 문자열 기반 표현식을 사용할 경우 "<string>" 을 써줍니다. 

 - mode 에는 컴파일된 코드를 eval() 함수로 처리하길 원할 경우 "eval" 을 써줍니다. 

 

##-- eval() for compiled-code-based input
compiled_code = compile("(2 + 3) * 10", "<string>", "eval")
eval(compiled_code)
# 50

 

 

 

 

[ Reference ]

* Real Python site: "Python eval(): Evaluate Expressions Dynamically
: https://realpython.com/python-eval-function/

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다 .

행복한 데이터 과학자 되세요! :-)

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 유닉스 스타일로 Python의 파일 경로와 파일명 패턴 매칭을 통해 찾아주는 glob, fnmatch 모듈에 대해서 알아보겠습니다. 

 

(1) glob: 유닉스 스타일 경로명 패턴 확장 (Unix style pathname pattern expansion)

(2) fnmatch: 유닉스 스타일 파일명 패턴 매칭 (Unix style filename pattern matching)

 

python glob, fnmatch module

 

 

(1) glob: 유닉스 스타일 경로명 패턴 확장 (Unix style pathname pattern expansion)

 

Python의 glob 모듈은 Unix shell에서 사용되는 규칙에 따라 지정된 패턴과 일치하는 모든 경로 이름을 찾아주며, 결과는 임의의 순서로 반환합니다. 

 

간단한 예를 들어서 설명해보겠습니다. 아래와 같은 파일경로의 계층으로 여러개의 파일이 있습니다. 

 

- data > glob 폴더내 'glob.ipynb' 파일, train 하위 폴더, test 하위 폴더

- data > glob > train 폴더 내 '1.txt', '2.txt', '1001.txt', '1002.txt', 'a.txt', 'b.txt', 'cat.jpeg'

- data > glob > test 폴더 내 '4.txt', '5.txt', 'd.txt', e.txt'

파일경로, 파일명 예시

 

 

(1-1) glob.glob('./*'): 현재 폴더의 폴더와 파일 경로 가져오기

 

import glob

## 현재 폴더의 폴더와 파일 경로
glob.glob('./*')

# ['./test', './glob.ipynb', './train']

 

 

(1-2) glob.glob(./foldername/*'): 특정 폴더 내 모든 파일 경로 가져오기

 

## ''./train' 경로의 모든 파일 경로
glob.glob('./train/*')

# ['./train/cat.jpeg',
#  './train/b.txt',
#  './train/a.txt',
#  './train/2.txt',
#  './train/1002.txt',
#  './train/1.txt',
#  './train/1001.txt']

 

 

(1-3) glob: 특정 폴더 내 특정 파일이름으로 끝나는 모든 파일 경로 가져오기 

 

예 1) '.txt' 로 끝나는 파일 경로

## '.txt' 로 끝나는 파일 경로
glob.glob('./train/*.txt')

# ['./train/b.txt',
#  './train/a.txt',
#  './train/2.txt',
#  './train/1002.txt',
#  './train/1.txt',
#  './train/1001.txt']

 

 

예 2) '.jpeg' 로 끝나는 파일 경로 

## '.jpeg' 로 끝나는 파일 경로
glob.glob('./train/*.jpeg')

# ['./train/cat.jpeg']

 

 

(1-4) glob.glob([0-9]*): 0~9 숫자로 시작하는 파일 경로 가져오기

 

## 0~9 숫자로 시작하는 파일 경로
glob.glob('./train/[0-9]*')

# ['./train/2.txt', 
#  './train/1002.txt', 
#  './train/1.txt', 
#  './train/1001.txt']

 

 

(1-5) glob.glob('./**/*', recursive=True)
  : 현재 폴더에 있는 폴더와 파일, 하위 폴더 내 모든 파일 경로 재귀적으로 가져오기

 

## ''**/*' 와 recursive=True : 현재 폴더에 있는 폴더와 파일, 하위 폴더 내 경로 재귀적으로 가져오기 
glob.glob('./**/*', recursive=True)

# ['./test',
#  './glob.ipynb',
#  './train',
#  './test/5.txt',
#  './test/4.txt',
#  './test/e.txt',
#  './test/d.txt',
#  './train/cat.jpeg',
#  './train/b.txt',
#  './train/a.txt',
#  './train/2.txt',
#  './train/1002.txt',
#  './train/1.txt',
#  './train/1001.txt']

 

 

(1-6) glob.glob('./**/*/', recursive=True): 현재 폴더에 있는 폴더 경로만 가져오기

 

## 제일 마지막에 '/' 추가: 폴더만
glob.glob('./**/*/', recursive=True)

# ['./test/', './train/']

 

 

(1-7) 디렉토리(<DIR>)와 파일(<FILE>) 구분자 추가해서 프린트 하기

 

import glob
from os.path import isdir

for x in glob.glob('./**/*', recursive=True):
    if isdir(x):
        print('<DIR> ', x) # 디렉토리
    else:
        print('<FILE>', x) # 파일
        
# <DIR>  ./test
# <FILE> ./glob.ipynb
# <DIR>  ./train
# <FILE> ./test/5.txt
# <FILE> ./test/4.txt
# <FILE> ./test/e.txt
# <FILE> ./test/d.txt
# <FILE> ./train/cat.jpeg
# <FILE> ./train/b.txt
# <FILE> ./train/a.txt
# <FILE> ./train/2.txt
# <FILE> ./train/1002.txt
# <FILE> ./train/1.txt
# <FILE> ./train/1001.txt

 

 

(1-8) 재귀하면서(recursive=True) 모든 폴더 내 파일 이름만 리스트로 가져오기

 

## 모든 폴더 내 파일 이름만 가져오기
import os

fnames = [
    os.path.basename(x) # 파일 이름
    for x in glob.glob('./**/*', recursive=True) # 재귀하면서 폴더&파일경로
    if not isdir(x) # 폴더 제외
]

print(fnames)

# ['glob.ipynb', 
#  '5.txt', 
#  '4.txt', 
#  'e.txt', 
#  'd.txt', 
#  'cat.jpeg', 
#  'b.txt', 
#  'a.txt', 
#  '2.txt', 
#  '1002.txt', 
#  '1.txt', 
#  '1001.txt']

 

 

(1-9) 재귀 대신 매뉴얼하게 모든 폴더를 지정해주어서 파일 이름만 리스트로 가져오기

 : 위의 (1-8) 재귀문과 결과 동일. 하위 폴더 개수가 많을 수록 (1-9) 수작업 코드 복잡해지고, 자동화에 제약 있음. 

 

## 파일 이름만 가져오기 : os.listdir() 이용해서
## 재귀 대신 매뉴얼하게 모든 폴더를 써줘야 함
import os

os.listdir('./') + os.listdir('./train/') + os.listdir('./test/')

# ['.DS_Store',
#  'test',
#  'glob.ipynb',
#  'train',
#  '.ipynb_checkpoints',
#  'cat.jpeg',
#  '.DS_Store',
#  'b.txt',
#  'a.txt',
#  '2.txt',
#  '1002.txt',
#  '1.txt',
#  '1001.txt',
#  '.DS_Store',
#  '5.txt',
#  '4.txt',
#  'e.txt',
#  'd.txt']

 

 

(1-10) 반복자(iterator) 반환하여 for loop 순환문에 사용하기

 

# glob.iglob(): 반복자(iterator) 반환
path_iterator = glob.iglob('./train/**.txt')

for path in path_iterator:
    print(path)
    
# ./train/b.txt
# ./train/a.txt
# ./train/2.txt
# ./train/1002.txt
# ./train/1.txt
# ./train/1001.txt

 

 

 

(2) fnmatch: 유닉스 스타일 파일명 패턴 매칭 (Unix style filename pattern matching)

 

fnmatch.fnmatch(filename, pattern) 메소드는 faiename 문자열이 pattern 문자열과 일치하는지를 검사하여, True나 False 를 반환합니다. 패턴 매칭하는 구문은 아래와 같습니다. 

 

    [seq] : seq 의 모든 문자와 일치합니다. 

    * : 모든 것과 일치합니다. 

 

 

(2-1) 특정 폴더 내 숫자로 시작('[0-9]*')하는 모든 파일 이름 가져오기

 

## filename 문자열이 pattern 문자열과 일치하는지를 검사하여, True 나 False를 반환합니다.
import fnmatch
import os

for file in os.listdir('./train'):
    # [seq]  seq의 모든 문자와 일치합니다.
    # *      모든 것과 일치합니다
    if fnmatch.fnmatch(file, '[0-9]*'):
        print(file)
        
# 2.txt
# 1002.txt
# 1.txt
# 1001.txt

 

 

(2-2) 특정 폴더 내 문자로 시작([!0-9]*')하는 모든 파일 이름 가져오기

 

for file in os.listdir('./train'):
    # [!seq] seq에 없는 모든 문자와 일치합니다
    if fnmatch.fnmatch(file, '[!0-9]*'):
        print(file)
        
# cat.jpeg
# b.txt
# a.txt

 

 

(2-3) 특정 폴더 내 특정 문자열로 끝나는 파일 이름 가져오기

 

for file in os.listdir('./train'):
    # *      모든 것과 일치합니다
    if fnmatch.fnmatch(file, '*.jpeg'):
        print(file)
        
# cat.jpeg

 

 

(2-4) 특정 폴더 내 모든 단일 문자('?')와 일치하는 파일 이름 가져오기

 

for file in os.listdir('./train'):
    # ?      모든 단일 문자와 일치합니다
    if fnmatch.fnmatch(file, '?.txt'):
        print(file)
        
# b.txt
# a.txt
# 2.txt
# 1.txt

 

 

(2-5) 특정 폴더 내 모든 파일 이름 가져오기

 

for file in os.listdir('./train'):
    # *      모든 것과 일치합니다
    if fnmatch.fnmatch(file, '*.txt'):
        print(file)
        
# b.txt
# a.txt
# 2.txt
# 1002.txt
# 1.txt
# 1001.txt

 

 

 

[Reference]

- glob module: https://docs.python.org/3/library/glob.html

- fnmatch module: https://docs.python.org/3/library/fnmatch.html#module-fnmatch

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요! :-)

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 Python을 사용해서 파워포인트와 PDF 파일에서 텍스트를 추출하는 방법을 소개하겠습니다. 

 

(1) 파워포인트 파일에서 텍스트 추출하기 (Extracting text from a PowerPoint file)

(2) PDF 파일에서 텍스트 추출하기 (Extracting text from a PDF file)

 

 

예제로 사용할 파워포인트와 PDF 파일 첨부합니다. 

 

* 예제 파워포인트 파일: "서울관광명소.pptx"

서울관광명소.pptx
0.04MB

 

* 예제 PDF 파일: "서울관광명소.pdf"

서울관광명소.pdf
0.05MB

 

 

 

예제로 사용하는 "서울관광명소.pptx" 파일은 아래와 같이 텍스트로 구성되어 있습니다. 

 

파워포인트 예시

 

 

(1) 파워포인트 파일에서 텍스트 추출하기 (Extracting text from a PowerPoint file)

 

Python으로 파워포인트에 파일에서 텍스트를 추출하기 위해서 먼저 테미널에서 "python-pptx" 모듈을 설치합니다. 

 

% python -m pip install python-pptx

 

 

파워포인트 파일이 저장되어 있는 경로와 파일 이름을 설정해주고, python-pptx 모듈을 사용해서 파워포인트 파일로 부터 텍스트를 추출해보겠습니다. 

 

이때 가독성을 높이기 위해서 각 슬라이드의 제목(title)을 Key 로 하고, 각 슬라이드의 본문 내용을 Value 로 하는 사전형(Dictionary) 형태로 추출한 텍스트를 저장해보겠습니다. 

 

## setting directory and file names
base_dir = "/Users/lhongdon/Documents/" # set with yours
ppt_nm = "서울관광명소.pptx"
pdf_nm = "서울관광명소.pdf"

ppt_path = base_dir + ppt_nm
pdf_path = base_dir + pdf_nm

print(ppt_path)
print(pdf_path)
# /Users/lhongdon/Documents/서울관광명소.pptx
# /Users/lhongdon/Documents/서울관광명소.pdf


## (1) extracting text from a PowerPoint file
from pptx import Presentation

prs = Presentation(ppt_path)

# text_runs will be populated with a list of strings,
# one for each text run in presentation
text_runs = {}

for slide in prs.slides:
    text_run = []
    for shape in slide.shapes:
        if not shape.has_text_frame:
            continue
        for paragraph in shape.text_frame.paragraphs:
            for run in paragraph.runs:
                text_run.append(run.text)

    text_runs[text_run[0]] = text_run[1:]
    
    
    
 print(text_runs)

# {'서울의 관광 명소': ['서울의 랜드마크', '서울의 고궁', '서울의 미술관과 박물관'],
#  '서울의 랜드마크': ['명동성당', '익선동 한옥거리', '광화문광장 야경', '롯데월드타워', '서울광장', '청와대'],
#  '서울의 고궁': ['경복궁', '창덕궁', '창경궁', '덕수궁', '서울 한양도성', '홍인지문', '숭례문'],
#  '서울의 미술관과 박물관': ['호림박물관', '갤러리 학고재', '별마당 도서관', '전쟁기념관', '국립중앙박물관']}

 

 

 

(2) PDF 파일에서 텍스트 추출하기 (Extracting text from a PDF file)

 

Python의 PyPDF2 모듈을 이용해서 PDF 파일로 부터 텍스트를 추출하기 위해, 먼저 터미널에서 "PyPDF2" 모듈을 설치합니다.  

 

% python -m pip install PyPDF2

 

 

다음으로, PdfReader() 메소드를 사용해서 각 PDF 페이지로부터 텍스트를 추출해서 text_all 이라는 리스트에 차곡차곡 합쳐보도록 하겠습니다. 

 

from PyPDF2 import PdfReader

## initiate PdfReader
reader = PdfReader(pdf_path)

print(len(reader.pages))
# 4


## extract text from a pdf file
text_all = []

for page in reader.pages:
    text = page.extract_text()
    text_all.append(text)
    


print(text_all)
# ['서울의관광명소1.서울의랜드마크2.서울의고궁3.서울의미술관과박물관',
#  '서울의랜드마크•명동성당•익선동한옥거리•광화문광장야경•롯데월드타워•서울광장•청와대',
#  '서울의고궁•경복궁•창덕궁•창경궁•덕수궁•서울한양도성•홍인지문•숭례문',
#  '서울의미술관과박물관•호림박물관•갤러리학고재•별마당도서관•전쟁기념관•국립중앙박물관']

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 여러개의 Python 패키지, 모듈을 한꺼번에 설치하는 방법을 소개하겠습니다. 

 

(1) 설치하고자 하는 Python 패키지, 모듈 목록을 text 파일로 만들기

(2) 터미널에서 Python 패키지 목록 text 파일이 저장된 경로로 이동하기

(3) $ pip install -r requirements.txt 로 한꺼번에 Python 패키지 설치하기

(4) Python 패키지 설치 여부 확인하기

 

 

(1) 설치하고자 하는 Python 패키지, 모듈 목록을 text 파일로 만들기

 

예시로서 requirements.txt 파일에 아래의 화면 캡쳐한 것처럼 설치가 필요한 Python 패키지의 이름과 (필요 시) 버전을 적어서 정리하였습니다. 

 

Python package requirements

 

 

 

(2) 터미널에서 Python 패키지 목록 text 파일이 저장된 경로로 이동하기

 

터미널에서 shell script 를 사용해서 위의 (1)번에서 작성한 requirement.txt 파일이 저장되어 있는 파일 경로로 이동합니다. 

 

아래 예제에서는 /Users/lhongdon/Documents/my_project/requirements.txt 에 저장해두었으며,

$ cat requirements.txt 로 텍스트 파일에 정리해놓은 파이썬 모듈 리스트를 확인해볼 수 있습니다. 

 

-- current working directory
(base) lhongdon@lhongdon0MD6T ~ % pwd
/Users/lhongdon


-- display directories and files
(base) lhongdon@lhongdon0MD6T ~ % ls
??????			Hello-World		VirtualBox VMs		iCloud Drive (Archive)	postgres-data
??????.pub		Library			anaconda3		kubernetes		seaborn-data
Applications		Movies			df.csv			minikf			ssh-key-hdlee2u
Desktop			Music			examples		minikf-kubeconfig	ssh-key-hdlee2u.pub
Documents		Pictures		git-tutorial		nltk_data
Downloads		Public			github			opt
(base) lhongdon@lhongdon0MD6T ~ % 


-- move to the directory where requirements.txt file is saved
(base) lhongdon@lhongdon0MD6T ~ % cd Documents 
(base) lhongdon@lhongdon0MD6T Documents % ls
1_GPDB_DS_Training					my_project
2_KNOU								Modern-Computer-Vision-with-PyTorch-master
3_proposals							array_select
4_project							data
5_seminar							demo
7_personal							
8_Rfriend							
9_CV_PyTorch					

(base) lhongdon@lhongdon0MD6T Documents % cd my_project 
(base) lhongdon@lhongdon0MD6T my_project % 
(base) lhongdon@lhongdon0MD6T my_project % ls
requirements.txt
(base) lhongdon@lhongdon0MD6T my_project % 


-- display the contents in requirements.txt
(base) lhongdon@lhongdon0MD6T my_project % cat requirements.txt 
psycopg2
sqlalchemy==1.4.39
sql_magic
ipython-sql==0.3.9
pgspecial==1.11.5
pmdarima

(base) lhongdon@lhongdon0MD6T my_project %

 

 

 

(3) $ pip install -r requirements.txt 로 한꺼번에 Python 패키지 설치하기

 

터미널에서 requirements.txt 파일이 저장되어 있는 경로로 이동한 상태에서 

 

% pip install -r requirements.txt 

 

를 실행하면 requirements.txt 파일에 일목요연하게 정리되어있는 Python 모듈이 순차적으로 설치가 됩니다. 

 

-- installing multiple python modules
(base) lhongdon@lhongdon0MD6T my_project % pip install -r requirements.txt


Collecting psycopg2 (from -r requirements.txt (line 1))
  Downloading psycopg2-2.9.6.tar.gz (383 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 384.0/384.0 kB 667.4 kB/s eta 0:00:00
  Preparing metadata (setup.py) ... done
Requirement already satisfied: sqlalchemy==1.4.39 in /Users/lhongdon/anaconda3/lib/python3.10/site-packages (from -r requirements.txt (line 2)) (1.4.39)
Collecting sql_magic (from -r requirements.txt (line 3))
  Downloading sql_magic-0.0.4-py3-none-any.whl (10 kB)
Collecting ipython-sql==0.3.9 (from -r requirements.txt (line 4))
  Downloading ipython_sql-0.3.9-py2.py3-none-any.whl (21 kB)
Collecting pgspecial==1.11.5 (from -r requirements.txt (line 5))
  Downloading pgspecial-1.11.5.tar.gz (42 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 42.9/42.9 kB 1.3 MB/s eta 0:00:00
  Preparing metadata (setup.py) ... done
Collecting pmdarima (from -r requirements.txt (line 6))
  Downloading pmdarima-2.0.3-cp310-cp310-macosx_10_9_x86_64.whl (607 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 607.3/607.3 kB 2.7 MB/s eta 0:00:00
Requirement already satisfied: greenlet!=0.4.17 in /Users/lhongdon/anaconda3/lib/python3.10/site-packages (from sqlalchemy==1.4.39->-r requirements.txt (line 2)) (2.0.1)
Collecting prettytable (from ipython-sql==0.3.9->-r requirements.txt (line 4))
  Downloading prettytable-3.8.0-py3-none-any.whl (27 kB)
Requirement already satisfied: ipython>=1.0 in /Users/lhongdon/anaconda3/lib/python3.10/site-packages (from ipython-sql==0.3.9->-r requirements.txt (line 4)) (8.10.0)
Collecting sqlparse (from ipython-sql==0.3.9->-r requirements.txt (line 4))
  Downloading sqlparse-0.4.4-py3-none-any.whl (41 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 41.2/41.2 kB 1.3 MB/s eta 0:00:00
Requirement already satisfied: six in /Users/lhongdon/anaconda3/lib/python3.10/site-packages (from ipython-sql==0.3.9->-r requirements.txt (line 4)) (1.16.0)
-- 이하 생략

 

 

 

(4) Python 패키지 설치 여부 확인하기

 

터미널에서 

% pip show [Python Module Name] 

 

을 실행하면 해당 Python 모듈의 설치 여부 및 상세 내역을 확인할 수 있습니다. 

 

-- check the details of python module installed
(base) lhongdon@lhongdon0MD6T my_project % pip show sql_magic

Name: sql-magic
Version: 0.0.4
Summary: UNKNOWN
Home-page: UNKNOWN
Author: Chris Rawles
Author-email: crawles@gmail.com
License: UNKNOWN
Location: /Users/lhongdon/anaconda3/lib/python3.10/site-packages
Requires: findspark, ipython, jupyter, pandas, sqlparse, traitlets
Required-by: 
(base) lhongdon@lhongdon0MD6T my_project % 
(base) lhongdon@lhongdon0MD6T my_project %

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,