PL(Programming Language)/Python

[Python] Pandas Explode, Pandas Dataframe, column split 바이오데이터 처리로 다지는 Pandas 라이브러리

탱젤 2021. 1. 13. 22:33

(실제 코드 결과로 작성, transcription factor binding site 데이터 이용)

  • Dataframe에 새로운 column 작성하기
  • Dataframe의 column split 후 다른 column으로 저장하기 # df[열이름].str.split() 이용
  • Dataframe의 열 data를 split 후 다시 저장하기
  • Pandas explode 메소드 사용하기 (데이터프레임 열에 리스트로 저장된 데이터에서 리스트 요소를 행으로 추가하기)
import pandas as pd

f1 = pd.read_csv('test.txt', delimiter = '\t', names = ['1', '2', '3', '4', '5', '6', '7', '8', '9'])
# 1~9로 열 이름 정해서 탭으로 분리된 파일 불러오기

 

내가 가진 data

위의 data를 보면 column name이 9인 열의 데이터가 합쳐져 있다.

한 줄의 data를 가져온 결과

binding_matrix_stable_id=ENSPFM0404;stable_id=ENSM00648832284;transcription_factor_complex=MYBL1::ONECUT2;epigenomes_with_experimental_evidence=GM12878%2CK562%2CHepG2%2CH1-hESC_3%2CHCT116

인데, 이 data를 각각 binding_matrix_stable_id, stable_id, transcription_factor_complex, epigenomes_with_experimental_evidence로 분리한 후 새로운 열로 지정하는 게 목표이다. 

 

그런데 여기서 epigenomes_with_experimental_evidence는 없는 data도 상당히 많아서 ';'으로 분리한 결과의 길이에 따라 데이터프레임을 다시 만든 후 분리할 예정.

lst = f1['9'].str.split(';') # ;으로 분리 후 분리된 길이의 결과를 데이터프레임의 열로 추가
lst_len = lst.str.len()
f1['lst_len'] = lst_len

lst_len 열이 새로 생성된 것을 볼 수 있다.

 

이후 lst_len 이 3인 것과 4인 것으로 분리해 새로운 데이터프레임 생성.

# df1: len = 3인 경우
# df1: len = 4인 경우
df1 = f1[f1['lst_len'] == 3]
df2 = f1[f1['lst_len'] == 4]

print(df1) 결과

# df1 column 분리 후 split
lst = df1['9'].str.split(';').str[0]
lst2 = df1['9'].str.split(';').str[1]
lst3 = df1['9'].str.split(';').str[2]
del df1['9']
df1['binding_matrix_stable_id'] = lst
df1['stable_id'] = lst2
df1['transcription_factor_complex'] = lst3

df1 column 분리 후 split 한 결과

내가 원하는 대로 column이 분리된 결과를 볼 수 있음 !!!

 

이제

binding_matrix_stable_id=ENSPFM0404

이런 식으로 생긴 data를 '=' 기준으로 분리할 것

lst = df1['binding_matrix_stable_id'].str.split('=').str[1]
lst2 = df1['stable_id'].str.split('=').str[1]
lst3 = df1['transcription_factor_complex'].str.split('=').str[1]
df1['binding_matrix_stable_id'] = lst
df1['stable_id'] = lst2
df1['transcription_factor_complex'] = lst3

역시나 내가 원하는 대로 딱 id, transcription_factor_complex 데이터로 잘 분리된 데이터프레임을 볼 수 있음.

 

이제 가장 문제였던(트롤,,,) transcription_factor_complex 열의 data를 split해서 행으로 추가할 것

transcription_factor_complex=CEBPE%2CGCM1::CEBPB%2CCEBPG%2CCEBPB%2CTEAD4::CEBPD%2CCEBPD

위 data를 보면 %와 ::을 경계로 모든 transcription_factor_complex가 합쳐져 있다. 이걸 분리해서 행으로 붙일 것이다.

complex_new = df1['transcription_factor_complex'].str.split('%') # %로 분리한 결과를 complex_new에 list로 저장
df1['transcription_factor_complex'] = complex_new # list로 저장한 결과를 열에 덮어씌우기

위처럼 list 형태로 transcription_factor_complex 열에 저장된 것을 볼 수 있다.

여기서 pandas explode를 이용해 작성한 함수로 column의 list 안의 것들을 행으로 추가할 것이다.

def unnest(df, tile, explode):
    vals = df[explode].sum(1)
    rs = [len(r) for r in vals]
    a = np.repeat(df[tile].values, rs, axis=0)
    b = np.concatenate(vals.values)
    d = np.column_stack((a, b))
    return pd.DataFrame(d, columns = tile +  ['_'.join(explode)])

함수 선언 후

df1 = unnest(df1, ['1','2','3','4','5','6','7','8','binding_matrix_stable_id','stable_id'], ['transcription_factor_complex'])
# 기준이 되는 열을 2번째 인자로, 분리할 열을 3번째 인자로 호출

 실행하면

%로 잘 분리되어 추가된 행을 볼 수 있다.

이제 위에 했던 방법처럼 '::'도 분리해 전처리 완성~!~!

:: 분리 과정은 위랑 똑같으니까 생략 ㅎㅎ

바이오 데이터라 개수가 엄청 많음...

 

Transcription Factor Binding Site 전처리 끝~

 

 

728x90