데이터분석 프로젝트 중 약 250만개의 데이터를 분류하는 파트에서의 문제.

 

Dataframe의 append 함수를 사용해서 같은 dataframe 변수에 리스트처럼 계속 분류된 값들을 추가하는 작업이었다.

그런데 대략 80만정도를 넘어가니 주피터 노트북에서 속도가 상당히 느려지면서

1시간동안 100만개 밖에 분류를 못하는 상황이 벌어졌다. 

속도 문제로 130만개쯤에서 중단.

 

 

 

문제의 코드 예시

#대량의 데이터를 담은 원본 데이터프레임
origin

#분류한 데이터를 나눠담을 데이터프레임들
d1 = pd.Dataframe(column=['c1', 'c2', 'c3'])
d2 = pd.Dataframe(column=['c1', 'c2', 'c3'])
d3 = pd.Dataframe(column=['c1', 'c2', 'c3'])

#반복문
for idx, row in origin.iterrows():
	if(row.c1 == 1): d1 = d1.append(row, ignore_index=True)
	elif(row.c1 == 2): d2 = d2.append(row, ignore_index=True)
	elif(row.c1 == 3): d3 = d3.append(row, ignore_index=True)

 

 

 

원인을 생각해보니 append 함수는 기존 프레임 뒤에 한 데이터를 추가해 새로운 프레임을 만드는 방식이었다.

즉, 데이터가 하나 들어갈 때마다 하나만 넣는게 아닌 처음부터 새로 넣는 방식이었던 것 같다.

(정정 사항이 있다면 댓글 부탁드립니다)

 

 

 

따라서 검색 결과 찾아낸 딕셔너리를 이용한 방식

#대량의 데이터를 담은 원본 데이터프레임
origin

#분류한 데이터를 나눠담을 딕셔너리들
d1 = {}
d2 = {}
d3 = {}
idx_d1 = 0
idx_d2 = 0
idx_d3 = 0


#각 딕셔너리에 데이터를 추가할 함수
def addRow(col_idx, group, data):
    if(group == 1):
        d1[col_idx] = data
    elif(group == 2):
        d2[col_idx] = data
    elif(group == 3):
        d3[col_idx] = data


#반복문
for idx, row in origin.iterrows():

	data = {"c1":row.c1, "c2":row.c2, "c3":row.c3}
    
	if(row.c1 == 1):
    	addRow(idx1, 1, data)
	elif(row.c1 == 2):
    	addRow(idx2, 2, data)
	elif(row.c1 == 3):
    	addRow(idx3, 3, data)

 

 

 

딕셔너리의 키를 인덱스로 활용하면 앞선 방식보다 몇 배는 빠른 성능을 낼 수 있었다.

이후 딕셔너리를 dataframe으로 만들거나, json화해서 파일시스템에 저장하는 등 변형이 자유롭다.

반응형

+ Recent posts