이번 포스팅에서는 데이터 프레임, 튜플, 리스트를 특정한 기준에 따라서 정렬, 재배치하는 방법에 대해서 알아보겠습니다.

 

오름차순 혹은 내림차순으로 정렬을 한 후에 상위 n개 (or 하위 n개), 혹은 첫번째 행 (or 마지막 행) 을 선택해야할 필요가 있을 때 사용할 수 있는 method, function 입니다.

 

DataFrame, Tuple, List 정렬 순서대로 소개하겠습니다.

 

 - (1) DataFrame 정렬 : DataFrame.sort_values()

 

 - (2) Tuple 정렬 : sorted(tuple, key)

 

 - (3) List 정렬 : list.sort(), sorted(list)

 

* 참고: Numpy 배열 정렬 np.sort()http://rfriend.tistory.com/357

 

 

 

 

  (1) DataFrame 정렬 : DataFrame.sort_values()

 

먼저 필요한 모듈을 불러오고, 예제 DataFrame을 만들어보겠습니다.

 

 

In [1]: import pandas as pd


In [2]: personnel_df = pd.DataFrame({'sequence': [1, 3, 2],

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

   ...: 'age': [30, 20, 40]})


In [3]: personnel_df

Out[3]:

   age  name  sequence
0   30  park         1
1   20   lee         3
2   40  choi         2

 

 

 

 

(1-1) 'sequence' 열(by='sequence')을 기준으로 index(axis=0) 오름차순 정렬하기

 

 

# sorting index of DataFrame by a specific column : axis=0, columns

In [4]: personnel_df.sort_values(by=['sequence'], axis=0)

Out[4]:

   age  name  sequence
0
   30  park         1
2   40  choi         2
1
   20   lee          3

 

 

 

 

(1-2) 내림차순(descending)으로 정렬하기 : ascending=False

 

 

# sorting index of dataFrame in descending order : ascending=False

In [5]: personnel_df.sort_values(by=['sequence'], axis=0, ascending=False)

Out[5]:

   age  name  sequence
1   20   lee         3
2   40  choi         2
0   30  park         1

 

 

 

 

(1-3) 열 이름을 (알파벳 순서로) 정렬하기 :  axis=1

 

 

# sorting columns of DataFrame : axis=1

In [6]: personnel_df.sort(axis=1)

Out[6]:

   age  name  sequence
0   30  park         1
1   20   lee         3
2   40  choi         2

 

# sorting columns of DataFrame in descending order : axis=1, ascending=False

In [7]: personnel_df.sort(axis=1, ascending=False

Out[7]:

   sequence  name  age
0         1  park   30
1         3   lee   20
2         2  choi   40

 

 

 

 

(1-4) DataFrame 자체 내에서 정렬된 상태로 다시 저장하기 : inplace=True

 

 

In [8]: personnel_df

Out[8]:

age name sequence

0 30 park 1

1 20 lee 3

2 40 choi 2


# sorting DataFarme in-place : inplace=True

In [9]: personnel_df.sort_values(by=['sequence'], axis=0, inplace=True)


In [10]: personnel_df

Out[10]:

age name sequence

0 30 park 1

2 40 choi 2

1 20 lee 3

 

 

 

 

(1-5) 결측값을 처음에(na_position='first'), 혹은 마지막(na_position='last') 위치에 정렬하기

 

 

# putting NaN to DataFrame

In [11]: import numpy as np


In [12]: personnel_df = pd.DataFrame({'sequence': [1, 3, np.nan],

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

    ...: 'age': [30, 20, 40]})

    ...:


In [13]: personnel_df

Out[13]:

   age  name  sequence
0   30  park       1.0
1   20   lee       3.0
2   40  choi       NaN

 


# first puts NaNs at the beginning : na_position='first'

In [14]: personnel_df.sort_values(by=['sequence'], axis=0, na_position='first')

Out[14]:

   age  name  sequence
2   40  choi       NaN
0   30  park       1.0
1   20   lee       3.0

 


# last puts NaNs at the end : na_position='last'

In [15]: personnel_df.sort_values(by=['sequence'], axis=0, na_position='last')

Out[15]:

   age  name  sequence
0   30  park       1.0
1   20   lee       3.0
2   40  choi       NaN

 

 

 

 

  (2) Tuple 정렬하기 : sorted(tuple, key) method

 

 

# making a tuple

In [16]: personnel_tuple = [(1, 'park', 30),

    ...: (3, 'lee', 20),

    ...: (2, 'choi', 40)]


In [17]: personnel_tuple

Out[17]: [(1, 'park', 30), (3, 'lee', 20), (2, 'choi', 40)]

 


# use 'key' parameter to specify a function to be called on

# sort by sequence number

In [18]: sorted(personnel_tuple, key=lambda personnel: personnel[0])

Out[18]: [(1, 'park', 30), (2, 'choi', 40), (3, 'lee', 20)]


# sort by name

In [19]: sorted(personnel_tuple, key=lambda personnel: personnel[1])

Out[19]: [(2, 'choi', 40), (3, 'lee', 20), (1, 'park', 30)]

 

# sort by age

In [20]: sorted(personnel_tuple, key=lambda personnel: personnel[2])

Out[20]: [(3, 'lee', 20), (1, 'park', 30), (2, 'choi', 40)]

 

 

 

내림차순(descending order)으로 정렬하고 싶으면 'reverse=True' 옵션을 설정해주면 됩니다.

 

 

# sorting tuple in descending order by age : reverse=True

In [21]: sorted(personnel_tuple, reverse=True, key=lambda personnel: personnel[2])

Out[21]: [(2, 'choi', 40), (1, 'park', 30), (3, 'lee', 20)]

 

 

 

 

  (3) List 정렬하기 : sorted(list), or list.sort()

 

 

 

# making a list

In [23]: my_list = [0, 1, 2, 3, 4, 9, 8, 7, 6, 5]

 


# (1) sorting a list : sort(list) function

In [24]: sorted(my_list)

Out[24]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

 

 

# (2) sorting a list : list.sort() method

In [25]: my_list.sort()


In [26]: my_list

Out[26]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

 


# sorting a list in descending order : reverse=True

In [27]: sorted(my_list, reverse=True)

Out[27]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]


In [28]: my_list.sort(reverse=True)


In [29]: my_list

Out[29]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

 

 

 

 

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

 

 

728x90
반응형
Posted by Rfriend
,

데이터 분석을 하다 보면 여기 저기 흩어져 있는 데이터를 특정한 Key를 기준으로 병합해서 분석해야 하는 경우가 매우 많습니다.

 

지난번 포스팅에서는 DataFrame을 pandas의 concat() 함수를 이용해서 합치는 방법, append() 함수를 사용해서 합치는 방법을 소개하였습니다.

 

이번 포스팅에서는 SQL을 사용해서 Database의 Table 들을 Join/Merge 하는 것과 유사하게 Python pandas의 pd.merge() 함수를 사용해서 DataFrame을 Key 기준으로 inner, outer, left, outer join 하여 합치는 방법을 소개하도록 하겠습니다.

 

SQL을 사용하는데 익숙한 분석가라면 매우 쉽고 빠르게 이해하실 수 있을 것입니다. 그리고 Python의 merge() 기능은 메모리 상에서 매우 빠르게 작동함으로 사용하는데 있어 불편함이 덜할 것 같습니다.

 

 

 

 

 

pandas merge 함수 설정값들은 아래와 같이 여러개가 있는데요, 이중에서  'how'와 'on'은 꼭 기억해두셔야 합니다.

 

 

pd.merge(left, right, # merge할 DataFrame 객체 이름
             how='inner', # left, rigth, inner (default), outer
             on=None, # merge의 기준이 되는 Key 변수
             left_on=None, # 왼쪽 DataFrame의 변수를 Key로 사용
             right_on=None, # 오른쪽 DataFrame의 변수를 Key로 사용
             left_index=False, # 만약 True 라면, 왼쪽 DataFrame의 index를 merge Key로 사용
             right_index=False, # 만약 True 라면, 오른쪽 DataFrame의 index를 merge Key로 사용
             sort=True, # merge 된 후의 DataFrame을 join Key 기준으로 정렬
             suffixes=('_x', '_y'), # 중복되는 변수 이름에 대해 접두사 부여 (defaults to '_x', '_y'
             copy=True, # merge할 DataFrame을 복사
             indicator=False) # 병합된 이후의 DataFrame에 left_only, right_only, both 등의 출처를 알 수 있는 부가 정보 변수 추가

 

 

 

먼저, pandas, DataFrame library를 importing 한 후에, 2개의 DataFrame을 만들어보겠습니다.

 

 

In [1]: import pandas as pd


In [2]: from pandas import DataFrame


In [3]: df_left = DataFrame({'KEY': ['K0', 'K1', 'K2', 'K3'],

   ...: 'A': ['A0', 'A1', 'A2', 'A3'],

   ...: 'B': ['B0', 'B1', 'B2', 'B3']})

   ...:


In [4]: df_right = DataFrame({'KEY': ['K2', 'K3', 'K4', 'K5'],

   ...: 'C': ['C2', 'C3', 'C4', 'C5'],

   ...: 'D': ['D2', 'D3', 'D4', 'D5']})

   ...:


In [5]: df_left

Out[5]:

    A   B KEY
0  A0  B0  K0
1  A1  B1  K1
2  A2  B2  K2
3  A3  B3  K3


In [6]: df_right

Out[6]:

    C   D KEY
0  C2  D2  K2
1  C3  D3  K3
2  C4  D4  K4
3  C5  D5  K5

 

 

 

 

 

'how' 의 left, right, inner, outer 별로 위에서 만든 'df_left'와 'df_right' 두 개의 DataFrame을 'KEY' 변수를 기준으로 merge 해보겠습니다.  SQL join에 익숙하신 분이라면 쉽게 이해할 수 있을 것입니다.

 

 

  (1) Merge method : left (SQL join name : LEFT OUTER JOIN)

 

 

In [7]: df_merge_how_left = pd.merge(df_left, df_right,

   ...: how='left',

   ...: on='KEY')

   ...:


In [8]: df_merge_how_left

Out[8]:

     A   B   KEY   C     D
0  A0  B0  K0  NaN  NaN
1  A1  B1  K1  NaN  NaN
2  A2  B2  K2   C2   D2
3  A3  B3  K3   C3   D3 

 

 

 

 

  (2) Merge method : right (SQL join name : RIGHT OUTER JOIN)

 

 

In [9]: df_merge_how_right = pd.merge(df_left, df_right,

   ...: how='right',

   ...: on='KEY')


In [10]: df_merge_how_right

Out[10]:

     A    KEY   C   D
0   A2   B2  K2  C2  D2
1   A3   B3  K3  C3  D3
2  NaN  NaN  K4  C4  D4
3  NaN  NaN  K5  C5  D5

 

 

 

 

  (3) Merge method : inner (SQL join name : INNER JOIN)

 

 

In [11]: df_merge_how_inner = pd.merge(df_left, df_right,

    ...: how='inner', # default

    ...: on='KEY')

    ...:


In [12]: df_merge_how_inner

Out[12]:

    A   B KEY   C   D
0  A2  B2  K2  C2  D2
1  A3  B3  K3  C3  D3

 

 

 

 

  (4) Merge method : outer (SQL join name : FULL OUTER JOIN)

 

 

In [13]: df_merge_how_outer = pd.merge(df_left, df_right,

    ...: how='outer',

    ...: on='KEY')

    ...:


In [14]: df_merge_how_outer

Out[14]:

     A    B  KEY    C    D
0   A0   B0  K0  NaN  NaN
1   A1   B1  K1  NaN  NaN
2   A2   B2  K2   C2   D2
3   A3   B3  K3   C3   D3
4  NaN  NaN  K4   C4   D4
5  NaN  NaN  K5   C5   D5

 

 

 

[참고] Hive 조인 문 : INNER JOIN, LEFT OUTER JOIN, RIGHT OUTER JOIN, FULL JOIN, CARTESIAN PRODUCT JOIN, MAP-SIDE JOIN, UNION ALL : http://rfriend.tistory.com/216

 

 

 

  (5) indicator = True : 병합된 이후의 DataFrame에 left_only, right_only, both 등의 

                              출처를 알 수 있는 부가정보 변수 추가

 

 

In [15]: pd.merge(df_left, df_right, how='outer', on='KEY',

    ...: indicator=True)

Out[15]:

     A    B KEY    C    D      _merge
0   A0   B0  K0  NaN  NaN   left_only
1   A1   B1  K1  NaN  NaN   left_only
2   A2   B2  K2   C2   D2        both
3   A3   B3  K3   C3   D3        both
4  NaN  NaN  K4   C4   D4  right_only
5  NaN  NaN  K5   C5   D5  right_only

 

 

 

위에서는 indicator=True로 했더니 '_merge'라는 새로운 변수가 생겼습니다.

 

이 방법 외에도, 아래처럼 indicator='변수 이름(예: indicator_info)'을 설정해주면, 새로운 변수 이름에 indicator 정보가 반환됩니다.

 

 

In [16]: pd.merge(df_left, df_right, how='outer', on='KEY',

    ...: indicator='indicator_info')

Out[16]:

     A    B KEY    C    D indicator_info
0   A0   B0  K0  NaN  NaN      left_only
1   A1   B1  K1  NaN  NaN      left_only
2   A2   B2  K2   C2   D2           both
3   A3   B3  K3   C3   D3           both
4  NaN  NaN  K4   C4   D4     right_only
5  NaN  NaN  K5   C5   D5     right_only

 

 

 

 

  (6) 변수 이름이 중복될 경우 접미사 붙이기 : suffixes = ('_x', '_y')

 

'B'와 'C' 의 변수 이름이 동일하게 있는 두 개의 DataFrame을 만든 후에, KEY를 기준으로 합치기(merge)를 해보겠습니다.  변수 이름이 중복되므로 Data Source를 구분할 수 있도록 suffixes = ('string', 'string') 을 사용해서 중복되는 변수의 뒷 부분에 접미사를 추가해보겠습니다.  default는 suffixes = ('_x', '_y') 입니다.

 

 

# making DataFrames with overlapping columns

In [17]: df_left_2 = DataFrame({'KEY': ['K0', 'K1', 'K2', 'K3'],

    ...: 'A': ['A0', 'A1', 'A2', 'A3'],

    ...: 'B': ['B0', 'B1', 'B2', 'B3'],

    ...: 'C': ['C0', 'C1', 'C2', 'C3']})


In [18]: df_right_2 = DataFrame({'KEY': ['K0', 'K1', 'K2', 'K3'],

    ...: 'B': ['B0_2', 'B1_2', 'B2_2', 'B3_2'],

    ...: 'C': ['C0_2', 'C1_2', 'C2_2', 'C3_2'],

    ...: 'D': ['D0_2', 'D1_2', 'D2_2', 'D3_3']})

    ...:


In [19]: df_left_2

Out[19]:

    A   B   C KEY
0  A0  B0  C0  K0
1  A1  B1  C1  K1
2  A2  B2  C2  K2
3  A3  B3  C3  K3


In [20]: df_right_2

Out[20]:

      B     C     D KEY
0  B0_2  C0_2  D0_2  K0
1  B1_2  C1_2  D1_2  K1
2  B2_2  C2_2  D2_2  K2
3  B3_2  C3_2  D3_3  K3

 


# adding string suffixes to apply to overlapping columns

In [21]: pd.merge(df_left_2, df_right_2, how='inner', on='KEY',

    ...: suffixes=('_left', '_right'))

    ...:

Out[21]:

    A B_left C_left KEY B_right C_right     D
0  A0     B0     C0  K0    B0_2    C0_2  D0_2
1  A1     B1     C1  K1    B1_2    C1_2  D1_2
2  A2     B2     C2  K2    B2_2    C2_2  D2_2
3  A3     B3     C3  K3    B3_2    C3_2  D3_3

 


# suffixes defaults to ('_x', '_y') 

In [22]: pd.merge(df_left_2, df_right_2, how='inner', on='KEY')

    ...:

Out[22]:

    A B_x C_x KEY   B_y   C_y     D
0  A0  B0  C0  K0  B0_2  C0_2  D0_2
1  A1  B1  C1  K1  B1_2  C1_2  D1_2
2  A2  B2  C2  K2  B2_2  C2_2  D2_2
3  A3  B3  C3  K3  B3_2  C3_2  D3_3

 

 

 

 

 

left_on, right_on, left_index, right_index 에 대해서는 다음번 포스팅에서 소개하도록 하겠습니다.

 

728x90
반응형
Posted by Rfriend
,