지난번 포스팅에서는 Python pandas의 pd.read_excel() 함수를 사용하여 외부의 Excel 파일을 읽어와서 pandas DataFrame으로 만드는 방법(https://rfriend.tistory.com/464)을 소개하였습니다. 


이번 포스팅에서는 반대로 Python pandas의 to_excel() 메소드를 사용하여 pandas DataFrame을 Excel 파일에 내보내서 쓰는 방법을 소개하겠습니다. 


(1) 하나의 DataFrame을 하나의 Excel Sheet에 쓰기

(2) 두 개 이상의 DataFrame을 여러개의 Excel Sheets에 나누어서 쓰기



 (1) 하나의 DataFrame을 하나의 Excel Sheet에 쓰기


먼저 필요한 라이브러리를 불러오고 Excel 파일로 저장할 경로와 파일 이름을 설정하겠습니다.


In [1]: import numpy as np

   ...: import pandas as pd

   ...: import os


In [2]: base_dir = "C:/Users/admin/Documents/data"

   ...: file_nm = "df.xlsx"

   ...: xlxs_dir = os.path.join(base_dir, file_nm) 



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


In [3]: df = pd.DataFrame({'group': ['a', 'b', 'c', 'd', 'e'],

   ...: 'value_1': [10.056, 20.534, 30.90, 41.9423, 35.21],

   ...: 'value_2': [200, 500, 600, np.nan, 1200]},

   ...: index = [1, 2, 3, 4, 5])


In [4]: df

Out[4]:

  group  value_1  value_2

1     a  10.0560    200.0

2     b  20.5340    500.0

3     c  30.9000    600.0

4     d  41.9423      NaN

5     e  35.2100   1200.0



이제 준비가 되었으니 'df'라는 이름의 DataFrame을 'df.xlxs' 라는 이름의 Excel 파일로 내보내기 (쓰기)를 to_excel() 메소드를 사용하여 해보겠습니다. 


#-- write an object to an Excel sheet using pd.DataFrame.to_excel()

df.to_excel(xlxs_dir, # directory and file name to write

            sheet_name = 'Sheet1', 

            na_rep = 'NaN', 

            float_format = "%.2f", 

            header = True, 

            #columns = ["group", "value_1", "value_2"], # if header is False

            index = True, 

            index_label = "id", 

            startrow = 1, 

            startcol = 1, 

            #engine = 'xlsxwriter', 

            freeze_panes = (2, 0)

            ) 



위의 df.to_excel() 을 실행시켰더니 아래와 같이 'df.xlsx' 라는 이름의 Excel ('C:/Users/admin/Documents/data\\df.xlsx')에 'Sheet1' 의 sheet (sheet_name = 'Sheet1')에 df DataFrame이 잘 쓰여졌음을 확인할 수 있습니다. 




'value_1' 칼럼은 부동소수형의 숫자가 들어있는데요, 자리수가 소수점 2자리 (float_format = "%.2f") 까지 반올림 되어서 보기에 좋게 제시가 되었습니다. 


'value_2' 칼럼에 결측값이 포함되어 있는데요, 엑셀에는 'NaN'으로 표기(na_rep = 'NaN')가 되어있습니다. 


열 이름은 DataFrame의 칼럼 이름(header = True)을 그대로 가져와서 사용하였으며, DataFrame의 index를 'id'라는 이름의 칼럼(index = True, index_label = "id")으로 내보냈습니다. 


엑셀에 DataFrame을 쓸 때 처음 시작하는 행과 열의 위치를 2행, 2열로 지정(startrow = 1, startcol = 1)하였습니다. 


그리고, 2행을 기준으로 틀 고정(freeze_panes = (2, 0))을 시켰습니다. 




 (2) 두 개 이상의 DataFrame을 여러개의 Excel Sheets에 나누어서 쓰기


예제로 사용할 두 개의 Python pandas DataFrame을 만들어보겠습니다. 


In [8]: df_1 = df.copy()


In [9]: df_2 = pd.DataFrame(np.arange(15).reshape(5, 3),

   ...: columns = ['col_1', 'col_2', 'col_3'],

   ...: index = [1, 2, 3, 4, 5])


In [10]: df_1

Out[10]:

  group  value_1  value_2

1     a  10.0560    200.0

2     b  20.5340    500.0

3     c  30.9000    600.0

4     d  41.9423      NaN

5     e  35.2100   1200.0


In [11]: df_2

Out[11]:

   col_1  col_2  col_3

1      0      1      2

2      3      4      5

3      6      7      8

4      9     10     11

5     12     13     14



이제 'df_1'과 'df_2' 라는 이름의 2개의 DataFrame을 (1)번과 똑같은 경로의, 똑같은 파일 이름('C:/Users/admin/Documents/data\\df.xlsx') 으로 내보내서 써보겠습니다. 이렇게 동일한 파일 경로/이름을 사용하면 기존의 엑셀 파일을 덮어쓰기(overwirte) 해버리므로 기존 파일의 내용은 지워져버립니다 (주의 요망). 


2개 이상의 DataFrame을 하나의 엑셀 파일에 여러개의 Sheets 로 나누어서 쓰려면 먼저 pd.ExcelWriter() 객체를 지정한 후에, sheet_name 을 나누어서 지정하여 써주어야 합니다. 


# Write two DataFrames to Excel using to_excel(). Need to specify an ExcelWriter object first.

with pd.ExcelWriter(xlxs_dir) as writer:

    df_1.to_excel(writer, sheet_name = 'DF_1')

    df_2.to_excel(writer, sheet_name = 'DF_2') 



'DF_1'과 'DF_2' 라는 이름의 Sheets 로 나누어서 2개의 DataFrame이 잘 쓰여졌음을 알 수 있습니다. 






만약 같은 경로/이름의 Excel 파일이 열려있는 상태에서 df.to_excel() 을 실행하게 되면 "PermissionError: [Errno 13] Permission denied:" 에러가 발생합니다. 이때는 열려있는 Excel 파일을 닫고 df.to_excel() 을 다시 실행하던가 (덮어쓰기를 해도 괜찮다는 가정하에), 아니면 저장할 Excel 파일의 경로/이름을 바꾸어주기 바랍니다. 


In [13]: with pd.ExcelWriter(xlxs_dir) as writer:

    ...: df_1.to_excel(writer, sheet_name = 'DF_1')

    ...: df_2.to_excel(writer, sheet_name = 'DF_2')

    ...:

    ...:

Traceback (most recent call last):


File "<ipython-input-13-9ba7e09cf9e3>", line 3, in <module>

df_2.to_excel(writer, sheet_name = 'DF_2')


File "C:\Users\admin\Anaconda3\lib\site-packages\pandas\io\excel.py", line 1191, in __exit__

self.close()


File "C:\Users\admin\Anaconda3\lib\site-packages\pandas\io\excel.py", line 1195, in close

return self.save()


 .... 중간 생략 ....


File "C:\Users\admin\Anaconda3\lib\site-packages\xlsxwriter\workbook.py", line 611, in _store_workbook

allowZip64=self.allow_zip64)


File "C:\Users\admin\Anaconda3\lib\zipfile.py", line 1009, in __init__

self.fp = io.open(file, filemode)


PermissionError: [Errno 13] Permission denied: 'C:/Users/admin/Documents/data\\df.xlsx' 



많은 도움이 되었기를 바랍니다. 

이번 포스팅이 도움이 되었다면 아래의 '공감~'를 꾹 눌러주세요. :-)



728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 사용자 정의함수(User Defined Function)에서 가변 매개변수(variable-length arguments, arbitrary arguments)의 위치에 따라서 일반 매개변수의 Keyword Argument 호출 여부에 따른 SyntaxError, TypeError 가 발생하는 현상을 살펴보고, 올바른 사용법을 소개하겠습니다. 


이게 은근히 헷갈리는 면이 있으므로 이번에 정확하게 알아두면 좋겠습니다. 





매개변수의 수를 다르게 해서 사용할 수 있는 가변 매개변수(variable-length arguments, arbitrary arguments) 위치가 뒤에 있는지, 아니면 앞에 있는지에 따라 2개 유형으로 나누어서 Keyword argument 의 올바른 사용법과 Error 발생 유형을 설명하겠습니다. 



  (1) 이름을 지정한 일반 매개변수를 앞에, 가변 매개변수를 뒤에 정의한 함수

      (Keyword argument First, Variable-length Arguments Second)


(1-1) 올바른 사용법: Keyword argument 사용 안함 (Without Keyword argument name)


In [1]: def repeat_str_KeyArg_first(repeat_num, *strings):

   ...: result = [repeat_num * strings]

   ...: return result

   ...:

   ...:


In [2]: repeat_str_KeyArg_first(3, 'a', 'b', 'c')

   ...:

Out[2]: [('a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c')] 



(1-2) Keyword argument를 사용해서 SystaxError가 발생하는 틀린 사용법
 => SyntaxError: positional arguments follows keyword argument


In [1]: def repeat_str_KeyArg_first(repeat_num, *strings):

   ...: result = [repeat_num * strings]

   ...: return result

   ...:

In [3]: repeat_str_KeyArg_first(repeat_num = 3, 'a', 'b', 'c') # SyntaxError

   ...:

File "<ipython-input-3-2047f5ba4020>", line 1

repeat_str_KeyArg_first(repeat_num = 3, 'a', 'b', 'c')

^

SyntaxError: positional argument follows keyword argument


File "<ipython-input-3-2047f5ba4020>", line 1

repeat_str_KeyArg_first(repeat_num = 3, 'a', 'b', 'c')

^

SyntaxError: positional argument follows keyword argument





  (2) 가변 매개변수를 앞에, 이름을 지정한 일반 매개변수를 뒤에 정의한 함수

      (Variable-length Arguments First, Keyword argument Second)


(2-1) 올바른 사용법: Keyword argument 사용함 (With Keyword argument name)


In [4]: def repeat_str_VarArg_first(*strings, repeat_num):

   ...: result = [repeat_num * strings]

   ...: return result

   ...:

   ...:


In [5]: repeat_str_VarArg_first('a', 'b', 'c', repeat_num = 3) # works well

   ...:

Out[5]: [('a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c')] 



(2-2) TypeError 발생하는 틀린 사용법 : 

  => TypeError: function() missing 1 required keyword-only argument: 'keyword_arg'


In [4]: def repeat_str_VarArg_first(*strings, repeat_num):

   ...: result = [repeat_num * strings]

   ...: return result

   ...:

   ...:

In [6]: repeat_str_VarArg_first('a', 'b', 'c', 3) # TypeError

   ...:

Traceback (most recent call last):


File "<ipython-input-6-13d658b54364>", line 1, in <module>

repeat_str_VarArg_first('a', 'b', 'c', 3)


TypeError: repeat_str_VarArg_first() missing 1 required keyword-only argument: 'repeat_num'


Traceback (most recent call last):


File "<ipython-input-6-13d658b54364>", line 1, in <module>

repeat_str_VarArg_first('a', 'b', 'c', 3)


TypeError: repeat_str_VarArg_first() missing 1 required keyword-only argument: 'repeat_num' 



많은 도움이 되었기를 바랍니다. 

이번 포스팅이 도움이 되었다면 아래의 '공감~'를 꾸욱 눌러주세요. :-)



728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 Python pandas의 read_excel() 함수를 사용하여 '엑셀 쉬트 데이터셋 (Excel sheet dataset)을 읽어와서 pandas DataFrame으로 만드는 방법'을 소개하겠습니다. 


아래의 첨부 파일은 예제로 사용할 'sales_per_region.xlsx. 라는 이름의 Excel file 입니다. 

sales_per_region.xlsx


위의 엑셀 자료를 읽어와서 Python pandas의 DataFrame으로 만들 때 아래의 요건을 충족시키고자 합니다. 

(1) 엑셀 자료로 부터 읽어올 데이터셋은 'Sheet1' 이름의 첫번째 쉬트에 있으며, 3행 A열 부터 ~ 10행 D열까지의 Cell에 있는 데이터입니다.  (sheet_name = 'Sheet1', header = 2)

(2) '3행은 칼럼 이름(header)'이며, 'A열의 'id' 칼럼은 index로 사용'하고자 합니다. (header = 2, index_col='id')

(3) 'region' 칼럼은 문자열(string), 'sales_representative' 칼럼은 정수형(integer), 'sales_amount' 칼럼은 부동소수형(float)의 데이터 형태(data type)입니다. (dtype = {'region': str, 'sales_representative': np.int64, 'sales_amount': float})

(4) pandas DataFrame으로 불러왔을 때 'sales_amount' 칼럼에 천 단위 구분 기호 콤마(',')는 없애고 싶습니다. (thousands = ',')

(5) 총 읽어올 행의 개수(number of rows)는 10개로 한정하고 싶습니다. (nrows=10)

(6) 11번째 행에 '# ignore this line' 처럼 '#' (comment character) 으로 시작하면 그 뒤의 행 전체는 무시하고자 합니다. (comment = '#')



# import libraries

 import numpy as np

 import pandas as pd

 import os


# set directory with yours

 base_dir = 'D:/admin/Documents'

 excel_file = 'sales_per_region.xlsx'

 excel_dir = os.path.join(base_dir, excel_file)


# read a excel file and make it as a DataFrame

 df_from_excel = pd.read_excel(excel_dir, # write your directory here

                              sheet_name = 'Sheet1', 

                              header = 2, 

                              #names = ['region', 'sales_representative', 'sales_amount']

                              dtype = {'region': str

                                         'sales_representative': np.int64

                                         'sales_amount': float}, # dictionary type

                              index_col = 'id', 

                              na_values = 'NaN', 

                              thousands = ',', 

                              nrows = 10, 

                              comment = '#')



혹시 엑셀 자료에 칼럼 이름(header)가 없다면 names = ['region', 'sales_representative', 'sales_amount'] 이런식으로 직접 칼럼 이름을 입력해주면 됩니다. 데이터가 있는 행과 열은 pandas가 알아서 찾아서 지정해주며, 데이터 형태(data type)도 일일이 지정해주지 않아도 알아서 추정을 해서 설정을 해줍니다. 


'sales_per_region.xlsx' 엑셀 파일을 'df_from_excel' 이라는 이름의 DataFrame으로 잘 불러왔습니다. 확인차 index, data type, 'region' 칼럼을 조회해보겠습니다. 제대로 잘 불러온거 맞지요?!


# check index

df_from_excel.index

Int64Index([1, 2, 3, 4, 5, 6, 7], dtype='int64', name='id')


# check data type


df_from_excel.dtypes

region                   object
sales_representative      int64
sales_amount            float64
dtype: object


# check 'region' column

df_from_excel['region']

id
1      seoul
2     inchon
3      busan
4    guangju
5      ulsan
6     sejong
7     jeunju
Name: region, dtype: object



많은 도움이 되었기를 바랍니다. 

Python pandas DataFrame을 Excel로 쓰기 (내보내기)를 하는 방법은 https://rfriend.tistory.com/466 를 참고하세요. 

이번 포스팅이 도움이 되었다면 아래의 '공감~'를 꾹 눌러주세요. :-)


728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 Python pandas DataFrame의 숫자형 변수에서 천 단위 숫자의 자리 구분 기호인 콤마(',')를 없애는 2가지 방법을 소개하겠습니다. 


예제로 사용할 데이터셋은 Wikipedia 에서 찾은 per capita nominal GDP for countries 2018년도 국가별 1인당 소득수준 (단위: US$) 데이터입니다.  아래의 데이터 캡쳐해놓은 그림처럼 1인당 소득수준(US$)의 숫자에 천 단위 자리 구분 기호로 콤마(comma, ',')가 들어있는데요, 이게 웹사이트나 엑셀에서 눈으로 보기에는 가독성이 좋습니다만, 분석을 할 때는 숫자형으로 인식을 하지 않고 문자열로 인식을 한다든지, 콤마(',')를 칼럼 구분자로 잘못 인식을 한다든지 해서 문제를 야기할 수 있습니다. 이에 천 단위 자리수 구분 기호 콤마(',' comma)를 없애는 2가지 방법을 소개하겠습니다. 

(1) pd.read_csv() 에서 thousands = ',' 옵션으로 천 단위 자리수 구분 콤마 없애고 불러오기

(2) DataFrame의 문자열 DataFrame.column.str.replace(',', '').astype('int64') 메소드를 이용하여 변환하기

(3) PostgreSQL, Greenplum DB에서 천 단위 자리수 구분 콤마 없애기


per_capita_GDP_for_countries.txt


 (1) pd.read_csv() 에서 thousands = ',' 옵션 설정하여 
      text, csv file을 불러올 때 천 단위 자리수 구분 없애고 불러오기

원천 데이터를 pd.read_csv() 함수로 불러올 때 천 단위 구분 기호를 신경 안쓰고, 데이터 경로와 구분자(탭, delimiter = '\t') 정도만 설정해주고 불러오면 아래처럼 'USD' 칼럼에 숫자가 천 단위마다 구분 기호 콤마(',')가 포함되어 있습니다. 

In [1]: import pandas as pd

In [2]: import os


In [3]: base_dir = 'D:/admin/Documents/'


In [4]: file_nm = 'per_capita_GDP_for_countries.txt'


In [5]: data_dir = os.path.join(base_dir, file_nm)


In [6]: per_capita_1 = pd.read_csv(data_dir, delimiter = '\t')


In [7]: per_capita_1.head(10)

Out[7]:

   Rank Country/Territory      USD

0     1        Luxembourg  114,234

1     2       Switzerland   82,950

2     2             Macau   82,388

3     3            Norway   81,695

4     4           Ireland   76,099

5     5           Iceland   74,278

6     6             Qatar   70,780

7     7         Singapore   64,041

8     8     United States   62,606

9     9           Denmark   60,692




이번에는 pd.read_csv() 함수에 thousands = ',' 라는 옵션을 추가해서 불어와 보겠습니다. 'USD' 칼럼에 천 단위 자리 구분 기호가 없어졌습니다.  아무래도 나중에 두번일 안하려면 데이터 불러올 때 부터 신경을 쓰는게 좋겠지요?!

In [8]: per_capita_2 = pd.read_csv(data_dir, delimiter = '\t', thousands = ',')


In [9]: per_capita_2.head(10)

Out[9]:

   Rank Country/Territory     USD

0     1        Luxembourg  114234

1     2       Switzerland   82950

2     2             Macau   82388

3     3            Norway   81695

4     4           Ireland   76099

5     5           Iceland   74278

6     6             Qatar   70780

7     7         Singapore   64041

8     8     United States   62606

9     9           Denmark   60692





 (2) DataFrame의 문자열 df.column.str.replace(',', '').astype('int64') 메소드
     이용하여 데이터 형태 및 유형 변환하기

이번에는 '소 잃고 외양간 고치기' 방법이 되겠습니다. -_-;

먼저, 'USD' 칼럼의 천 단위 구분 기호 콤마 ','를 그대로 불러왔던 첫번째의 'per_capita_1' DataFrame의 칼럼별 data type을 살펴보겠습니다. 'USD' 칼럼이 'object'로 되어있습니다. (정수형 integer 가 아닙니다!) 

In [10]: per_capita_1.dtypes

Out[10]:

Rank int64

Country/Territory object

USD object
dtype: object 


이제 문자열(string)의 replace() 메소드를 이용해서 콤마(',')를 비어있는 '' 로 변경(replace)하고, 데이터 형태를 정수형(integer64)로 지정(astype('int64')해보겠습니다. 애초 'USD' 칼럼이 'object' 형태였다면, str.replace(',', '').astype('int64')로 새로 만든 'USD_2' 칼럼은 'int64' 형태로 천 단위 숫자 구분 기호 콤마 없이 잘 들어가 있습니다. 

In [11]: per_capita_1['USD_2'] = per_capita_1.USD.str.replace(',', '').astype('int64')

In [12]: per_capita_1.dtypes

Out[12]:

Rank int64

Country/Territory object

USD object

USD_2 int64

dtype: object


In [13]: per_capita_1.head(10)

Out[13]:

   Rank Country/Territory      USD   USD_2

0     1        Luxembourg  114,234  114234

1     2       Switzerland   82,950   82950

2     2             Macau   82,388   82388

3     3            Norway   81,695   81695

4     4           Ireland   76,099   76099

5     5           Iceland   74,278   74278

6     6             Qatar   70,780   70780

7     7         Singapore   64,041   64041

8     8     United States   62,606   62606

9     9           Denmark   60,692   60692





  (3) PostgreSQL, Greenplum DB 에서 천 단위 구분 기호 콤마(',') 없애는 방법


DB에서도 천 단위 구분 기호 콤마가 골치거리인건 마찬가지이죠. 아래 SQL query 참고하세요. 

 SELECT replace(column_name, ',', '')::numeric

 FROM table_name


많은 도움이 되었기를 바랍니다. 

이번 포스팅이 도움이 되었다면 아래의 '공감~'를 꾹 눌러주세요. :-)


728x90
반응형
Posted by Rfriend
,

지난 포스팅에서는 Python pandas DataFrame을 csv 파일로 다운로드 한 후에 로컬에서  PostgreSQL, Greenplum DB에 Copy해서 넣는 방법 (https://rfriend.tistory.com/457) 을 소개하였습니다. 

 이번 포스팅에서는 Python pandas DataFrame을 csv 파일로 다운로드 하는 절차 없이, sqlalchemy engine과 to_sql() 함수를 이용하여 바로 직접 PostgreSQL, Greenplum DB에 쓰는 방법을 소개하겠습니다. 이렇게 하면 다운로드하는 절차가 필요없기 때문에 좀더 간편하고 workflow가 간소화되는 장점은 있는데요, csv로 내려서 copy 하는 것 대비 속도고 조금 더 느리다는 단점이 있습니다. 



먼저 예제로 사용할 간단한 DataFrame을 만들어보겠습니다. 


# make a sample DataFrame

import pandas as pd

score = pd.DataFrame({

        'date': ['2019-07-28']*4, 

        'name': ['kim', 'lee', 'choi', 'park'], 

        'age': [19, 20, 19, 20], 

        'math_score': [91, 95, 92, 70], 

        'pass_yn': [True, True, True, False]}, 

         columns=['date', 'name', 'age', 'math_score', 'pass_yn'])



이제 'score' 라는 이름의 pandas DataFrame을 Postgresql, Greenplum DB에 'score' 라는 Table 이름으로 public schema에 생성해서 써보겠습니다. 

이때 DB connection을 하기 위해 SQLAlchemy로 DB engine 을 생성해줘야 하는데요,
engine = sqlalchemy.create_engine("postgresql://user:password@host:port/database") 
의 순서대로 자신의 DB 설정값을 입력해주면 됩니다. (port 가 5432 디폴트 값이면 생략 가능)

 

import sqlalchemy

from sqlalchemy import create_engine

# engine = sqlalchemy.create_engine("postgresql://user:password@host:port/database")

engine = create_engine("postgresql://postgres:postgres@localhost:5432/postgres") # set yours


engine.execute("DROP TABLE IF EXISTS public.score;") # drop table if exists

score.to_sql(name = 'score', 

             con = engine

             schema = 'public', 

             if_exists = 'fail', # {'fail', 'replace', 'append'), default 'fail'

             index = True, 

             index_label = 'id', 

             chunksize = 2, 

             dtype = {

                     'id': sqlalchemy.types.INTEGER()

                     'date': sqlalchemy.DateTime()

                     'name': sqlalchemy.types.VARCHAR(100)

                     'age': sqlalchemy.types.INTEGER()

                     'math_score': sqlalchemy.types.Float(precision=3)

                     'pass_yn': sqlalchemy.types.Boolean()

                     })



'if_exists' 옵션에는 {'fail', 'replace', 'append'}의 3개가 존재하고, 디폴트는 'fail' 옵션입니다. 

  • if_exists = 'fail' : 같은 이름의 Table이 존재할 경우 ValueError 가 남
  • if_exists = 'replace'같은 이름의 Table이 존재할 경우 기존 Table을 Drop하고 새로운 값을 Insert함
  • if_exists = 'append': 같은 이름의 Table이 존재할 경우 기존 Table에 추가로 새로운 값을 Insert함


index = True 로 설정해주면 pandas DataFrame의 Index도 DB Table에 insert 해주며, index_label = 'xxx'로 index의 칼럼 이름을 부여해줄 수 있습니다. 


chunksize = xx 를 설정해주면 pandas DataFrame 데이터를 xx row 개수 만큼 DB table 에 insert를 해줍니다. 설정해주지 않으면 pandas DataFrame을 통째로 한꺼번에 insert를 합니다. 


dtype 은 pandas DataFrame의 각 변수별로 DB table에 넣어줄 Data Type을 사전형(Dictionary)으로 {'column': data_type} 형식으로 설정해줄 수 있습니다. 위의 예시에서 INTEGER, DateTime(), VARCHAR(), Float(), Boolean 데이터 형태 지정하는 것을 보여주었는데요, 대/소문자, 괄호() 여부를 위의 예시처럼 똑같이 사용해야 합니다. (괄호를 빼먹거나, 대/소문자가 틀리면 에러가 납니다)

참고로, to_sql() 에서 dtype 을 칼럼 별로 설정하지 않으면 전부 'text' 데이터 형태로 해서 DB table에 입력됩니다. 


확인차, DBeaver로 PostgreSQL에 score table을 조회해보겠습니다. Python pandas의 'score' DataFrame이 PostgreSQL의 score table로 데이터가 잘 들어갔네요! 


많은 도움이 되었기를 바랍니다.

이번 포스팅이 도움이 되었다면 아래의 '공감~'를 꾹 눌러주세요. 


728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 Python pandas의 DataFrame, Series 에서 특정 변수를 기준으로 순서를 구할 때 사용하는 rank() 함수를 소개하겠습니다. 

순위(Rank)는 정렬(Sort)와 밀접한 관련이 있는데요, 참고로 Python에서 자료형별 정렬(Sort) 방법은 아래 링크를 참고하세요. 


  (1) 다양한 동점 처리방법(tie-breaking methods)에 따른 순위(rank) 구하기 비교

순위(rank)를 구할 때 기준 변수의 점수(score)가 동일(tie)한 관측치를 어떻게 처리하는지에 따라서 5가지 방법이 있습니다. 

[ 순위 구할 때 동점 처리하는 5가지 방법 ]

  • 평균(method='average') : 동점 관측치 간의 그룹 내 평균 순위 부여 (default 설정)
  • 최소값(method='min') : 동점 관측치 그룹 내 최소 순위 부여
  • 최대값(method='max') : 동점 관측치 그룹 내 최대 순위 부여
  • 첫번째 값 (method='first') : 동점 관측치 중에서 데이터 상에서 먼저 나타나는 관측치부터 순위 부여
  • 조밀하게 (method='dense') : 최소값('min')과 같은 방법으로 순위부여하나, 'min'과는 다르게 그룹 간 순위가 '1'씩 증가함 (like ‘min’, but rank always increases by 1 between groups)


동점을 포함하고 있는 간단한 예제 DataFrame을 만들어보겠습니다. 

In [1]: import numpy as np


In [2]: import pandas as pd


In [3]: df = pd.DataFrame({

   ...: 'name': ['kim', 'lee', 'park', 'choi', 'jung', 'gang', 'nam'],

   ...: 'score': [70, 95, 100, 95, 70, 90, 70]

   ...: }, columns=['name', 'score'])


In [4]: df

Out[4]:

name score

0 kim 70

1 lee 95

2 park 100

3 choi 95

4 jung 70

5 gang 90

6 nam 70


이제 순위 구할 때 동점을 처리하는 5가지 방법별로 순위 결과가 어떻게 다른지 확인해보겠습니다. (예제를 시험점수로 가정하고, 점수가 높을 수록 상위 순위가 나오도록 함. ascending = False)

In [5]: df['rank_by_average'] = df['score'].rank(ascending=False) # rank default method='average

In [6]: df['rank_by_min'] = df['score'].rank(method='min', ascending=False)


In [7]: df['rank_by_max'] = df['score'].rank(method='max', ascending=False)


In [8]: df['rank_by_first'] = df['score'].rank(method='first', ascending=False)


In [9]: df['rank_by_dense'] = df['score'].rank(method='dense', ascending=False)


In [10]: df

Out[10]:

  name   score   rank_by_average    rank_by_min   rank_by_max    rank_by_first \

0 kim        70                   6.0              5.0              7.0              5.0

1 lee         95                   2.5              2.0              3.0              2.0

2 park      100                  1.0               1.0              1.0              1.0

3 choi        95                  2.5               2.0              3.0              3.0

4 jung        70                  6.0               5.0              7.0              6.0

5 gang       90                  4.0               4.0              4.0              4.0

6 nam        70                  6.0               5.0              7.0              7.0


rank_by_dense

0            4.0

1            2.0

2            1.0

3            2.0

4            4.0

5            3.0

6            4.0



  (2) 순위를 오름차순으로 구하기 (Rank in Ascending order)

rank(ascending = True) 으로 설정해주면 오름차순 (제일 작은 점수가 순위 '1'이고, 점수가 높아질수록 하나씩 순위 증가)으로 순위를 구합니다. Default 설정이 ascending=True 이므로 별도로 설정을 안해줘도 자동으로 오름차순 순위가 구해집니다. 

In [11]: df_score = df[['name', 'score']].copy()


In [12]: df_score['rank_ascending'] = df_score['score'].rank(method='min', ascending=True)


In [13]: df_score

Out[13]:

name    score     rank_ascending

0 kim        70                  1.0

1 lee         95                    5.0

2 park      100                    7.0

3 choi        95                    5.0

4 jung        70                    1.0

5 gang       90                    4.0

6 nam        70                    1.0 



  (3) 그룹 별로 순위 구하기 (Rank by Groups): df.groupby().rank()

Groupby operator를 사용하면 그룹별로 따로 따로 순위를 구할 수 있습니다. 

In [14]: from itertools import chain, repeat

    ...:


In [15]: df2 = pd.DataFrame({

    ...: 'name': ['kim', 'lee', 'park', 'choi']*3,

    ...: 'course': list(chain.from_iterable((repeat(course, 4)

    ...: for course in ['korean', 'english', 'math']))),

    ...: 'score': [70, 95, 100, 95, 65, 80, 95, 90, 100, 85, 90, 90]

    ...: }, columns=['name', 'course', 'score'])


In [16]: df2

Out[16]:

    name   course  score

0    kim   korean     70

1    lee   korean     95

2   park   korean    100

3   choi   korean     95

4    kim  english     65

5    lee  english     80

6   park  english     95

7   choi  english     90

8    kim     math    100

9    lee     math     85

10  park     math     90

11  choi     math     90


In [17]: df2['rank_by_min_per_course'] = df2.groupby('course')['score'].rank(method='min', ascending=False)


In [18]: df2

Out[18]:

    name   course  score  rank_by_min_per_course

0    kim   korean     70                     4.0

1    lee   korean      95                     2.0

2   park   korean    100                     1.0

3   choi   korean      95                     2.0

4    kim  english      65                     4.0

5    lee  english       80                     3.0

6   park  english      95                     1.0

7   choi  english      90                     2.0

8    kim     math    100                     1.0

9    lee     math      85                     4.0

10  park     math     90                     2.0

11  choi     math     90                     2.0



  (4) 칼럼을 기준으로 순위 구하기 (Rank over the columns): df.rank(axis=1)

위의 (1), (2), (3) 번의 예시는 전부 행을 기준(위/아래 방향)으로 한 순위(rank over the rows) 였습니다. 필요에 따라서는 열을 기준(왼쪽/오른쪽 방향)으로 한 순위(rank over the columns)을 해야할 때도 있을텐데요, rank(axis=1) 을 설정해주면 열 기준 순위를 구할 수 있습니다. 

In [19]: df3 = pd.DataFrame({

    ...: 'col_1': [1, 2, 3, 4],

    ...: 'col_2': [3, 5, 1, 2],

    ...: 'col_3': [3, 1, 2, 4]})


In [20]: df3

Out[20]:

 col_1 col_2 col_3

0   1      3      3

1   2      5      1

2   3      1      2

3   4      2      4


In [21]: df3.rank(method='min', ascending=False, axis=1)

Out[21]:

   col_1    col_2    col_3

0    3.0       1.0       1.0

1    2.0       1.0       3.0

2    1.0       3.0       2.0

3    1.0       3.0       1.0 


많은 도움이 되었기를 바랍니다. 

이번 포스팅이 도움이 되었다면 아래의 '공감~'를 꾹 눌러주세요. :-)


728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 Python pandas의 DataFrame, Series 에서 특정 칼럼 내에 특정 값을 가지고 있는 행 전체를 indexing 해오는 방법 2가지를 소개하겠습니다. 

(1) df.isin() 메소드를 이용한 DataFrame, Series 값 indexing 방법

(2) 비교 조건문 boolean 을 이용한 DataFrame, Series 값 indexing 방법

먼저 간단한 예제로 사용할 DataFrame을 만들어보겠습니다. 

In [1]: import pandas as pd


In [2]: df = pd.DataFrame({'id': ['a', 'b', 'c', 'd', 'e', 'f'],

   ...: 'var': [1, 2, 3, 4, 5, 6]})


In [3]: df

Out[3]:

id var

0 a 1

1 b 2

2 c 3

3 d 4

4 e 5

5 f 6



 (1) df.isin() 메소드를 이용한 DataFrame, Series 값 indexing 방법

pandas DataFrame이나 Series에 isin() 메소드를 사용하면 isin() 메소드 안의 값이 들어 있으면, 즉 소속이 되어 있으면 (membership) True를, 들어있지 않으면 False 를 반환합니다. 

In [4]: df['id'].isin(['b', 'e', 'k'])

Out[4]:

0 False

1 True

2 False

3 False

4 True

5 False

Name: id, dtype: bool 


이처럼 조건 값의 소속 여부를 Boolean 값으로 반환해주는 점을 이용하여, 특정 값이 들어있는 행을 DataFrame, Series에서 indexing 해올 수 있습니다.  위의 예제 'df' DataFrame의 'id' 칼럼에서 'b', 'e', 'k' 값이 들어있는 행 전체를 가져와 보겠습니다. 

In [5]: df[df['id'].isin(['b', 'e', 'k'])]

Out[5]:

id var

1 b  2
4 e  5 


만약 'id'라는 칼럼 혹은 'var'라는 칼럼 중에서 특정 값이 어느 한군데라도(OR) 소속이 되어있으면 행을 가져와 보겠습니다. 

In [6]: df[df['id'].isin(['b', 'e', 'k']) | df['var'].isin([1, 8])]

   ...:

Out[6]:

id var

0 a 1

1 b 2
4 e 5 



 (2) 비교 조건문 boolean 을 이용한 DataFrame, Series 값 indexing 방법

위의 isin() 메소드를 이용한 [6]번째 실행 셀의 결과와 동일한 값을 indexing 해오는 것을, 이번에는 조건문 boolean 을 이용해서 해보겠습니다. 아무래도 위의 [6]번 isin() 메소드를 썼을 때보다 '|'(OR)를 모든 비교 조건문을 연결하다 보니 코드가 더 길고 복잡합니다. 

따라서, 특정 값이 포함/ 소속 (Membership) 여부를 조건으로 해서 DataFrame, Series로부터 행 전체를 indexing해와야 하는 경우 isin() 메소드를 유용하게 사용할 수 있습니다. (물론 아래의 비교 조건문의 경우 단지 포함/소속 여부 많이 아닌 모든 조건문에 범용적으로 사용할 수 있는 장점이 있습니다.)

In [7]: df[(df['id'] == 'b') | (df['id'] == 'e') | (df['id'] == 'k') | (df['var'] == 1) | (df['var'] == 8)]

Out[7]:

id var

0 a 1

1 b 2
4 e 5



 TypeError: cannot compare a dtyped [object] array with a scalar of type [bool] 

참고로, 여러개의 비교 조건문을 & (AND), 또는 | (OR) 로 연결해서 다수개의 조건을 AND, 또는 OR로 만족하는 행을 가져오고 싶을 경우 반드시 조건문에 (조건문) & (조건문), (조건문) | (조건문) 처럼 조건문에 괄호 ( ) 를 꼭 쳐줘야 합니다. (Be sure to include the parentheses in the conditions)

In [8]: df[df['id'] == 'b' | df['id'] == 'e' | df['id'] == 'k']

Traceback (most recent call last):


File "<ipython-input-8-3140416d729c>", line 1, in <module>

df[df['id'] == 'b' | df['id'] == 'e' | df['id'] == 'k']


File "C:\Users\admin\Anaconda3\lib\site-packages\pandas\core\ops.py", line 836, in wrapper

na_op(self.values, other),


File "C:\Users\admin\Anaconda3\lib\site-packages\pandas\core\ops.py", line 807, in na_op

x.dtype, type(y).__name__))


TypeError: cannot compare a dtyped [object] array with a scalar of type [bool]


Traceback (most recent call last):


File "<ipython-input-8-3140416d729c>", line 1, in <module>

df[df['id'] == 'b' | df['id'] == 'e' | df['id'] == 'k']


File "C:\Users\admin\Anaconda3\lib\site-packages\pandas\core\ops.py", line 836, in wrapper

na_op(self.values, other),


File "C:\Users\admin\Anaconda3\lib\site-packages\pandas\core\ops.py", line 807, in na_op

x.dtype, type(y).__name__))


TypeError: cannot compare a dtyped [object] array with a scalar of type [bool]


TypeError가 안나게 제대로 조건문 boolean indexing을 하려면 아래처럼 비교 조건문별로 '(비교 조건문) | (비교 조건문) 처럼 괄호 ( ) 를 쳐주면 됩니다. 

In [9]: df[ (df['id'] == 'b') | (df['id'] == 'e') | (df['id'] == 'k')]

Out[9]:

id var

1 b 2
4 e 5 


많은 도움이 되었기를 바랍니다. 

이번 포스팅이 도움이 되었다면 아래의 '공감~'를 꾹 눌러주세요. :-)

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 빠르고 메모리를 효율적으로 사용해서 반복자((fast and memory-efficient iterator)를 만들어주는 itertools 모듈을 사용해서 리스트 원소를 n번 반복하고 묶어서 새로운 리스트를 만드는 4가지 유형의 방법을 소개하겠습니다. 


먼저 itertools 모듈에서 chain(), repeat() 함수를 불러오고, 예제로 사용할 반복할 리스트(numbers)와 반복할 회수(n)을 만들어놓겠습니다. 

 In [1]: from itertools import chain, repeat

In [2]: numbers = [1, 2, 3]


In [3]: n = 3


  (1) itertools.repeat(object, times) : object를 times 만큼 반복하기


itertools의 repeat() 함수로 [1, 2, 3] 리스트를 3번 반복하면, 아래처럼 리스트 안에 [1, 2, 3] 리스트가 각 각 분리([1, 2, 3], [1, 2, 3], [1, 2, 3])되어서 들어가 있습니다. 

 

In [4]: list(repeat(numbers, n))

Out[4]: [[1, 2, 3], [1, 2, 3], [1, 2, 3]]




  (2) itertools.chain.from_iterable(repeat(object, times))) 
      : times 만큼 "object 전체"를 반복한 연속된 서열을 하나의 서열로 묶어줌


위의 (1)번과는 다르게, [1, 2, 3, 1, 2, 3, 1, 2, 3] 의 단 하나의 리스트로 묶였습니다. 


In [5]: list(chain.from_iterable(repeat(numbers, n)))

Out[5]: [1, 2, 3, 1, 2, 3, 1, 2, 3]

 



  (3) itertools.chain.from_iterable((repeat(object, times) for object in objects)))
       : "objects 내 각 원소"를 times만큼 반복한 연속된 서열을 하나의 서열로 묶어줌

list comprehension 으로 for loop을 이용하여서 numbers 리스트 안의 각 원소인 1, 2, 3 별로 3번씩 반복한 후, 이를 하나의 리스트로 묶어준 경우입니다. 


In [6]: list(chain.from_iterable((repeat(number, n) for number in numbers)))

Out[6]: [1, 1, 1, 2, 2, 2, 3, 3, 3]

 



  (4) itertools.chain.from_iterable((repeat(object, time)
                                              for (object, time) in zip(objects, times))))

  : objects 내 각 원소 다른 수의 times 만큼 반복한 연속된 서열을 하나의 서열로 묶어줌

반복할 수 times 인자를 반복할 대상 objects 내 원소별로 다르게 하고 싶을 때가 있습니다. 이럴 때는 zip() 으로 반복할 대상 object와 반복할 회수 time을 짝으로 묶어서 반복을 시켜주면 됩니다. 


In [7]: numbers = [1, 2, 3]

   ...: n_list = [3, 5, 7]


In [8]: list(chain.from_iterable((repeat(number, n) for (number, n) in zip(numbers, n_list))))

Out[8]: [1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3] 



많은 도움이 되었기를 바랍니다. 

이번 포스팅이 도움이 되었다면 아래의 '공감~'를 꾸욱 눌러주세요. :-)


728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 Windows 환경에서 Anaconda Python 배포판으로 Python을 설치했을 경우에, Anaconda Prompt 를 이용하여 Python x.x 버전의 새로운 가상환경(Virtual Environment)을 만드는 방법을 소개하겠습니다. 

가상환경(Virtual Environment)을 이용하면 Python 버전 간의 의존성을 고려해서 가상의 격리된 환경을 만들어줌으로써 버전이 다름으로 인해 발생할 수 있는 호환이나 충돌 문제를 미연에 방지할 수 있도록 해줍니다. Anaconda Python 배포판에서는 conda command 로 가상환경, Python 패키지 설치를 관리할 수 있습니다. 


Anaconda Navigator에서 UI를 가지고 좀더 쉽게 가상환경을 만들 수도 있기는 한데요, 가끔 보면 Windows OS 노트북 사용하는 분들 중에 Anaconda Navigator 를 실행시켜면 화면으로 뜨는데 5분~10분 정도씩 걸리는 경우도 있더라구요. 그래서 빠르게 바로 실행시킬 수 있는 Anaconda Prompt 를 사용해서 가상환경 만드는 방법을 소개하겠습니다.  

먼저 Windows 실행 버튼을 눌러서 Anaconda Prompt 메뉴를 찾아 실행합니다.  python -V 커맨드로 확인해보니 저는 python 3.5.2 버전을 쓰고 있습니다. Python 2.7 버전으로 새로운 가상환경을 만들어보겠습니다. 

 > python -V



1. Conda 버전 확인 및 Conda Update


conda 를 최신버전으로 업데이트를 해줍니다. 중간에 Proceed ([y]/n)? 질문이 나오면 'y' 를 입력해줍니다. 

conda -V

conda update conda

Proceed ([y]/n)? y



 2. 가상환경 목록 확인 (Check virtual environments list)


 > conda env list

또는 

conda info -e



 3. conda로 가상환경 새로 만들기 (Create a new virtual environment using conda)

> conda create -n [virtual environment name] python=[python version] anaconda

의 형식과 순서대로 입력해줍니다. 저는 새로운 가상환경 이름을 'py_2.7'로 하였고, python 2.7 버전으로 anaconda 배포판을 이용해서 가상환경을 만들어보겠습니다. 

 conda create  -n  py_2.7  python=2.7  anaconda

이렇게 하면 아래처럼 Python 2.7 버전과 호환이 검증된 다른 Python libraries 들이 버전을 맞추어서 자동으로 수십개가 설치가 됩니다. 


중간에 Proceed ([y]/n)? 라고 묻거든 'y' 라고 답해주세요. 


혹시 SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed 라는 SSLError 가 발생하면 아래의 "conda config --set ssl_verify false"라는 command를 실행하고 난 후에, 위의 "conda create -n py_2.7 python=2.7 anaconda" 커맨드를 다시 실행시켜 보세요. 

 > conda config --set ssl_verify false

혹은 Anaconda Navigator의 Preference에서 'enable SSL verification' 옵션의 체크박스를 해제해주고 "conda create -n py_2.7 python=2.7 anaconda"를 다시 실행해보기 바랍니다. 


"py_2.7" 이라는 이름의 가상환경이 잘 만들어졌는지 확인해볼까요? (이번에는 "conda env list" 대신에 "conda info -e"를 사용해서 가상환경 목록 확인)

 


 4. 가상환경 활성화 하기 (Activate Virtual Environment)


"activate [virtual environment name]" 형식으로 커맨드를 입력해주면 해당 이름/ Python 버전의 가상환경이 활성화되어서 이용 가능해집니다. 방금 새로 만든 python 2.7 버전으로 설치한 "py_2.7" 이름의 가상환경을 활성화해보겠습니다. 
(참고로, Mac OS에서는 > source activate [virtual_env_name] 으로서, Windows랑 조금 다릅니다.)

 > activate py_2.7


아래 화면 캡쳐해놓은 것처럼 activate py_2.7 을 하고 나면 "(py_2.7) C:\Users\admin>" 과 같이 커서 화면이 바뀝니다. 



 5. IDE (Jupyter Notebook, Spyder, IPython) 실행하기

conda prompt 창에서 커맨드 명령문으로 "py_2.7" 이라는 이름의 가상환경에서 python 2.7 버전을 사용할 수 있게 Jupyter Notebook, Spyder, IPython 등의 IDE 를 실행시킬 수 있습니다. 

5-1. Jupyter Notebook 실행

 (py_2.7) > jupyter notebook 

아래처럼 웹브라우저가 뜨면서 Jupyter Notebook이 실행되면 우측 상단의 'New' 메뉴에서 'Python 2'를 선택해서 새로운 Notebook 화면을 생성합니다.

아래처럼 새로운 Notebook 화면이 뜨면 이름 설정해주고 사용하면 되겠습니다. 탐색적 데이터 분석이나 교육용으로 사용하기에는 Jupyter Notebook이 제격이지요. 

Jupyter Notebook 다 사용하였으면 저장하고, 노트북 홈 화면에서 작업한 파일 shutdown 하구요, conda prompt 창에서 'Ctrl + C' 해주면 jupyter notebook kernel 종료(kernel shutdown)하고 빠져나올 수 있습니다. 


5-2. Spyer 실행

 (py_2.7) > spyder

Python으로 Project별로 Production 하기에는 Spyder나 Pycharm 이 작업하기에 더 편한거 같습니다. 


5-3. IPython 실행

 (py_2.7) > IPython

그냥 가볍고, 깔끔하고, interactive 하게 코딩하고 싶으면 IPython 이용하면 되겠습니다. 



 6. 가상환경 비활성화/ 종료하기 (Deactivate a Virtual Environment)

가상환경을 종료하려면 > deactivate 해줍니다. 

(참고로, MacOS 사용자라면 > conda deactivate 로서, Windows와는 조금 다릅니다)

 (py_2.7) > deactivate

아래 화면 캡쳐한 것처럼 가상환경을 deactivate 해주면 "C:\Users\admin>" 으로 커서가 빠져나옵니다. 



 7. 가상환경 제거 하기 (Delete a Virtual Environment)

특정 Python 버전을 쓰는 프로젝트가 끝나서 더이상 쓸모가 없거나, 오래된 버전이라서 사용하지 않게 된 가상환경을 삭제하려면 > conda env remove -n [virtual environment name]  이라는 커맨드 명령어를 실행시켜줍니다. 

 > conda env remove -n py_2.7

그러면 자동으로 전체 가상환경 내 library 들을 지워주며, 다른 가상환경과는 격리되어 있기 때문에 아무런 영향없이 지워줍니다. 좋지요?! :-)


자동으로 버전 맞춰서 설치되었던 Python libraries 들을 지울건데 정말로 지워도 되냐고 확인 (Proceed ([y]/n)?)하려고 물어보는데요, y 라고 답해주기 바랍니다. 


> conda env list  로 가상환경 목록을 확인해보니 'py_2.7' 이라는 이름의 python 2.7 버전의 가상환경이 안보이네요. 잘 제거된거 맞네요. 


많은 도움이 되었기를 바랍니다. 

이번 포스팅이 도움이 되었다면 아래의 '공감~'를 꾹 눌러주세요. :-)


728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 Python pandas의 DataFrame을 Postgresql, Greenplum DB에 Copy 해서 집어넣는 방법을 소개하겠습니다. 

먼저 간단한 예제 pandas DataFrame을 만들어보겠습니다. 


import numpy as np

import pandas as pd


# make a DataFrame

school = pd.DataFrame({'region': ['gangnam', 'secho', 'bundang', 'mokdong'], 

                       'student_cnt': [100, 120, 150, 90], 

                       'math_score': [91, 95, 92, 93]}, 

                        columns=['region', 'student_cnt', 'math_score'])


school

Out[02]: 

    region  student_cnt  math_score

0  gangnam          100          91

1    secho          120          95

2  bundang          150          92

3  mokdong           90          93



이제 school 이라는 pandas DataFrame을 아래의 순서대로 DB에 Copy해서 넣어보겠습니다. 

(1) DataFrame을 CSV 파일로 내보내기 (export a DataFrame to CSV file)

(2) Postgresql, Greenplum DB에 연결하고 Table 만들기

(3) Postgresql, Greenplum DB의 Table에 CSV file을 Copy해서 집어넣기


  (1) DataFrame을 CSV 파일로 내보내기 (export a DataFrame to CSV file)


pandas의 to_csv() 메소드를 이용하였으며, index와 header 옵션은 False로 설정해서 CSV 파일에는 포함시키지 않도록 하겠습니다. 


school.to_csv('C:/Users/admin/Documents/data/school.csv', 

              sep=",", 

              na_rep="NaN", 

              index=False

              header=False)

 



  (2) Postgresql, Greenplum DB에 연결하고 Table 만들기

psycopg2 라이브러리를 이용해서 Postgresql, Greenplum DB에 연결해보겠습니다. 아래의 connect() 에는 본인의 DB 설정 정보를 바꾸어서 입력해주면 됩니다. 


# Postgresql DB connect using psycopg2

from psycopg2 import connect

conn = connect(host='localhost',  # set yours

               port=5432, 

               database='postgres', 

               user='postgres', 

               password='postgres')


cur = conn.cursor()


# Create a table at Postgresql public schema with school name

cur.execute("""

    DROP TABLE IF EXISTS school;

    CREATE TABLE school (

        region varchar(100), 

        student_cnt numeric, 

        math_score numeric

    )

""")

conn.commit()

 



  (3) Postgresql, Greenplum DB의 Table에 CSV file을 Copy해서 집어넣기

with open() 으로 로컬에 저장해놓은 school.csv 파일을 읽고, cursor.copy_expert() 를 이용하여 "COPY school FROM STDIN DELIMITER ',' CSV;" 쿼리문을 실행시켜서 CSV 파일을 Table 에 copy 해주겠습니다. 


query = """

    COPY school FROM STDIN DELIMITER ',' CSV;

"""


with open('C:/Users/admin/Documents/data/school.csv', 'r') as f:

    cur.copy_expert(query, f)

    

conn.commit()


# close connection

conn.close()

 


PGAdmin 에 들어가서 school 테이블을 조회해보니 아래처럼 데이터가 잘 copy 되서 들어가 있네요. 


Python에서 DB connect해서 데이터 조회하고 DataFrame으로 만들어서 한번 더 확인을 해보았습니다. 아래와 같이 데이터가 Postgresql DB의 school table에 잘 들어가 있음을 확인할 수 있습니다. 


# check 

cur.execute("SELECT * FROM school;")

school_df = cur.fetchall()

school_df

Out[39]: 

[('gangnam', Decimal('100'), Decimal('91')),

 ('secho', Decimal('120'), Decimal('95')),

 ('bundang', Decimal('150'), Decimal('92')),

 ('mokdong', Decimal('90'), Decimal('93'))] 



많은 도움이 되었기를 바랍니다. 



728x90
반응형
Posted by Rfriend
,