globals()
로 변수 저장원래 globals()는 디버깅용으로만 사용해야하는데, 그동안 변수를 만드는 데 globals()를 사용해왔다.
예를들면 다음과 같이...
import itertools
id_list = 'HLA-A HLA-B HLA-C'.split()
number_list = '9 10'.split()
for id, number in itertools.product(*[id_list, number_list]):
Dataframe = df_[df_['allele'].str.contains(id)]
Dataframe = df_[df_['length']==int(number)]
globals()[f'df_{id}_{number}'] = Dataframe
이러면 globals()[f'df_HLA-A-9']
부터 globals()[f'df_HLA-C-10']
까지 위 코드의 로직대로 Dataframe type의 변수가 생성된다.
얼핏보면 변수이름을 일일이 지정해주지 않아도 되고 굉장히 간편해보인다.
하지만 여기엔 많은 문제점이 있음! 예를들면 그 코드 자체를 돌릴 땐 문제가 되지 않는데, 저장해두고선 모듈로 불러올 때도 문제가 되고.. 등등 아무튼 여러가지 문제가 있다.
그래서 좋은 코드에선 globals()
는 디버깅용으로만 사용하고, 이런 목적(dataframe 저장)으로 사용하고자 할 땐 리스트, 튜플, 딕셔너리 등의 자료구조에 저장을 해서 불러오는 식으로 사용을 한다고 한다.
namedtuple
사용기따라서 본인은 이번에 namedtuple
을 사용하여 구현해보았다.
import itertools
Test = namedtuple('MakeNamedtuple', ['id', 'number', 'Dataframe'])
test_list = []
for id, number in itertools.product(*[id_list, number_list]):
Dataframe = df_[df_['allele'].str.contains(id)]
Dataframe = df_[df_['length']==int(number)]
test_list.append(Test(id, number, Dataframe))
이렇게 구현을 했다. 이제 몇 가지 확인을 통해 test_list
를 살펴보자.
print(len(test_list))
print(test_list[0].id)
# 결과
6
HLA-A-9
df_1 = test_list[0].Dataframe
df_2 = globals()[f'df_HLA-A_9']
print(df_1[(df_1 == df_2).all(axis=1) == False]) # 두 데이터프레임에서 서로 다른 요소가 있는지 확인하는 방법
# 결과
Empty DataFrame
전역변수를 사용하여 dataframe을 변수에 할당한 것과 namedtuple을 사용한 것이 일치하게 나왔다. 데이터를 관리하기도 훨씬 편하다.
결론 : namedtuple씁시다.
p.s. 참고로 namedtuple로 된 걸 그냥 저장하려하면 에러뜸.
cloudpickle이나 dill을 사용하거나..
전역변수 지역변수 문제로 인해 에러가 뜨므로 저장을 하려면 namedtuple class 자체를 함수 내에서 구현하고 저장해야됨.
=> 사실 뭔 말인지 아직 잘 모르겠음. 일단 돌아가니까 그냥 쓰고 시간남을 때 다시 공부 링크
from collections import namedtuple
import dill
import itertools
import pandas as pd
def SavePredictionList(df):
allele_list = 'HLA-A,HLA-B,HLA-C'.split(',')
length_list = '9,10'.split(',')
SavePred = namedtuple('Prediction', ['id', 'pred'])
prediction_list = []
for allele, length in itertools.product(*[allele_list, length_list]):
id = allele + '_' + length
total = df[df['allele'].str.contains(allele)]
total = df[df['length']==int(length)]
abe = SavePred(id, total)
prediction_list.append(abe)
with open(f'/home/hb/python/DeepNeo/data/result/1st_pred/{allele}_{length}.dill', 'wb') as f:
dill.dump(abe, f)
return prediction_list
prediction_list = SavePredictionList(df=merged)