'pandas DataFrame에 칼럼별로 lambda 함수를 적용해서 행 단위 함수를 적용하여 for loop 문을 사용하지 않고 새로운 칼럼 만들기'에 해당되는 글 1건

  1. 2019.12.26 [Python] 텍스트 문서 파싱하여 DataFrame으로 만들고, 그룹별로 Lag 해서 새로운 칼럼 만들기 21

이번 포스팅에서는 


(1) 텍스트 파일을 열어 각 Line 별로 읽어 들인 후에 문자열 메소드를 이용해 파싱(Parsing)

    --> pandas DataFrame으로 만들고, 


(2) ID를 기준으로 그룹별로 값을 한칸식 내려서(Lag) 새로운 칼럼을 만들기


를 해보겠습니다. 



아래와 같이 생긴 텍스트 파일이 있다고 하겠습니다. 

'color_range.txt' 파일

color_range.txt



첫번째 행 AAA는 0에서 100까지는 a 영역, 100부터 200까지는 b 영역이라는 의미입니다. 여기서 a(빨간색), b(파란색)은 색상을 나타내며, AAA 는 0(포함)부터 100(미포함)까지는 빨간색, 100(포함)부터 200(미포함)까지는 파란색, 200(포함)부터 300(미포함)까지는 빨간색, ... 을 의미합니다. 


이렇게 데이터가 행으로 옆으로 길게 늘여져서 쓰여진 파일을 'AAA', 'BBB' 의 ID별로 색깔(a: 빨간색, b: 파란색)별 시작 숫자와 끝 숫자를 알기 쉽게 각 칼럼으로 구분하여 pandas DataFrame으로 만들어보고자 합니다. 



  (1) 텍스트 파일을 열어 각 Line별로 읽어들인 후 문자열 메소드를 이용해 파싱(Parsing)

       --> pandas DataFrame 만들기



import pandas as pd

import os


# set file path

cwd = os.getcwd()

file_path = os.path.join(cwd, 'color_range.txt')



# read 'color_range.txt' file and parsing it by id and value

df = pd.DataFrame() # blank DataFrame to store results


# open file

f = open(file_path)


# parsing text line by line using for loop statement

for line in f.readlines():

    id_list = []

    color_list = []

    bin_list = []

    

    # remove white space

    line = line.strip()


    # delete '"'

    line = line.replace('"', '')

    

    # get ID and VALUE from a line

    id = line[:3]

    val = line[4:]

    

    # make a separator with comma(',')

    val = val.replace(' a', ',a')

    val = val.replace(' b', ',b')

    

    # split a line using separator ','

    val_split = val.split(sep=',')

    

    # get a 'ID', 'COLOR', 'BIN_END' values and append it to list

    for j in range(len(val_split)):

        id_list.append(id)

        color_list.append(val_split[j][:1])

        bin_list.append(val_split[j][2:])

    

    # make a temp DataFrame, having ID, COLOR, BIN_END values per each line

    # note: if a line has only one value(ie. Scalar), then it will erase 'index error'  :-(

    df_tmp = pd.DataFrame({'id': id_list, 

                           'color_cd': color_list, 

                           'bin_end': bin_list}

                         )

    

    # combine df and df_tmp one by one

    df = pd.concat([df, df_tmp], axis=0, ignore_index=True)



# let's check df DataFrame

df

[Out]:

idcolor_cdbin_end
0AAAa100
1AAAb200
2AAAa300
3AAAb400
4BBBa250
5BBBb350
6BBBa450
7BBBb550
8BBBa650
9BBBb750
10BBBa800
11BBBb910





  (2) ID를 기준으로 그룹별로 값을 한칸식 내려서(Lag) 새로운 칼럼을 만들기


'ID'를 기준으로 'bin_end' 칼럼을 한칸씩 내리고 (shift(1)), 첫번째 행의 결측값은 '0'으로 채워(fillna(0))보겠습니다. 



# lag 1 group by 'id' and fill missing value with '0'

df['bin_start'] = df.groupby('id')['bin_end'].shift(1).fillna(0)

[Out]:

idcolor_cdbin_endbin_start
0AAAa1000
1AAAb200100
2AAAa300200
3AAAb400300
4BBBa2500
5BBBb350250
6BBBa450350
7BBBb550450
8BBBa650550
9BBBb750650
10BBBa800750
11BBBb910800




color code ('color_cd')에서 'a' 는 빨간색(red), 'b'는 파란색(blue) 이라는 색깔 이름을 매핑해보겠습니다. 



# mapping color using color_cd

color_map = {'a': 'red', 

             'b': 'blue'}


df['color'] = df['color_cd'].map(lambda x: color_map.get(x, x))

df

[Out]:

idcolor_cdbin_endbin_startcolor
0AAAa1000red
1AAAb200100blue
2AAAa300200red
3AAAb400300blue
4BBBa2500red
5BBBb350250blue
6BBBa450350red
7BBBb550450blue
8BBBa650550red
9BBBb750650blue
10BBBa800750red
11BBBb910800blue




보기에 편리하도록 칼럼 순서를 'id', 'color_cd', 'color', 'bin_start', 'bin_end' 의 순서대로 재배열 해보겠습니다. 



# change the sequence of columns

df = df[['id', 'color_cd', 'color', 'bin_start', 'bin_end']]

df

[Out]:

idcolor_cdcolorbin_startbin_end
0AAAared0100
1AAAbblue100200
2AAAared200300
3AAAbblue300400
4BBBared0250
5BBBbblue250350
6BBBared350450
7BBBbblue450550
8BBBared550650
9BBBbblue650750
10BBBared750800
11BBBbblue800910

 



bin_start 는 포함하고 (include), bin_end 는 포함하지 않는(not include) 것을 알기 쉽도록 

 ==> 포함('[') 기호 + 'bin_start', 'bin_end' + 미포함(')') 기호를 덧붙여서 

'bin_range'라는 새로운 칼럼을 만들어보겠습니다. 



# make a 'Bin Range' column with include '[' and exclude ')' sign

df['bin_range'] = df['bin_start'].apply(lambda x: '[' + str(x) + ',') + \

    df['bin_end'].apply(lambda x: str(x + ')'))


df

[Out]:

idcolor_cdcolorbin_startbin_endbin_range
0AAAared0100[0,100)
1AAAbblue100200[100,200)
2AAAared200300[200,300)
3AAAbblue300400[300,400)
4BBBared0250[0,250)
5BBBbblue250350[250,350)
6BBBared350450[350,450)
7BBBbblue450550[450,550)
8BBBared550650[550,650)
9BBBbblue650750[650,750)
10BBBared750800[750,800)
11BBBbblue800910[800,910)

 



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

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


728x90
반응형
Posted by Rfriend
,