2017-05-13 3 views
2

"평면화"하고 싶은 사전이 있습니다 (ish) Series입니다. 내 문제/시험 재현하기 위해 나는 유사한 구조를 가진 Series을 만들었습니다일련의 사전을 DataFrame으로 효율적으로 변환하십시오.

>>> my_series = pd.Series([{'A': [1], 'B' : []}, {'A' : [1, 2], 'B' : [3, 4]}]) 
>>> my_series 
0   {u'A': [1], u'B': []} 
1 {u'A': [1, 2], u'B': [3, 4]} 
dtype: object 

다음 단계는 계층 적 색인이있는 'DataFrame'로 변환된다. 나는 기능적으로 작동하는 방법을 발견했다 :이 내가 원하는 걸 제공

>>> pd.DataFrame(pd.DataFrame.from_dict(row, orient='index').stack() for row in my_series) 
    A   B  
    0 1 0 1 
0 1.0 NaN NaN NaN 
1 1.0 2.0 3.0 4.0 

을,하지만 내 실제 데이터 세트에이 목록의 각 0-4 요소와 30,000 행을 약 60 초 복용, 엄청나게 느린 , 약 8G RAM을 사용합니다.

multiprocessing 모듈을 병렬로 사용하여 작업 속도를 높이려고 시도했지만 더 나은 방법이 있는지 여기에서 물을 것이라고 생각했습니다.

보다 합리적인 시간에 위와 동일한 결과를 얻을 수 있습니까?

+0

@Kasramvd 나는이 구축 된 방법 모르겠지만, 이것으로 볼 것이다 - 팁 주셔서 감사합니다 :) – arman

답변

1

당신은 DataFrame 생성자를 사용할 수 있지만 : 당신은 처음부터 시리즈의 건축을 통해 제어 할 수없는 경우에 따라서, 당신은 단지 DataFrame에 나열하고 전달하는 시리즈를 변환 할 수 있습니다 list에 다음 values에 의해 numpy arraySeries를 변환 : flatennig에 대한 다음

a = pd.DataFrame(my_series.values.tolist()) 
print (a) 
     A  B 
0  [1]  [] 
1 [1, 2] [3, 4] 

이 가능한 사용 concat입니다

list comprehension로 :

b = pd.concat([pd.DataFrame(a[x].values.tolist()) for x in a.columns], axis=1,keys=a.columns) 
print (b) 
    A   B  
    0 1 0 1 
0 1 NaN NaN NaN 
1 1 2.0 3.0 4.0 

배열을 NumPy와로 변환 인 경우가 빠르다 :

In [93]: %timeit pd.DataFrame(list(my_series)) 
1000 loops, best of 3: 550 µs per loop 

In [94]: %timeit pd.DataFrame(my_series.values.tolist()) 
1000 loops, best of 3: 516 µs per loop 
+0

나는 왜이 트릭이 시간을 몇 분에서 1 초도 줄 였는지 이해하지 못합니다.건배 :) – arman

1

먼저 팬더 기반 데이터 구조에 사전이 있으므로 시리즈 대신 DataFrame을 만들 수 있습니다.

두 번째로 DataFrame은 사전 목록을 허용하고 예상 결과를 구성 할 수 있습니다. 첫째

In [10]: pd.DataFrame(list(my_series)) 
Out[10]: 
     A  B 
0  [1]  [] 
1 [1, 2] [3, 4] 
0

설정

my_series = pd.Series([{'A': [1], 'B' : []}, {'A' : [1, 2], 'B' : [3, 4]}]) 
df = pd.DataFrame.from_dict(s.tolist()) 

솔루션 좋아

, 빠른 솔루션 작업을 얻었다.

idx = pd.MultiIndex.from_product([['A','B'],[0,1]]) 

pd.DataFrame(pd.DataFrame(df.values.flatten().tolist()).values.reshape(2,-1), columns=idx) 

Out[1051]: 
    A   B  
    0 1 0 1 
0 1.0 NaN NaN NaN 
1 1.0 2.0 3.0 4.0 

올드 솔루션

#Convert list elements to columns 
df_A = df.A.apply(pd.Series).stack().unstack() 
df_B = df.B.apply(pd.Series).stack().unstack() 
#rename columns 
df_A.columns = ['A_' + str(e) for e in df_A.columns] 
df_B.columns = ['B_' + str(e) for e in df_B.columns] 
#combine two dataframes 
pd.concat([df_A,df_B],axis=1) 

Out[973]: 
    A_0 A_1 B_0 B_1 
0 1.0 NaN NaN NaN 
1 1.0 2.0 3.0 4.0 

테스트

%timeit pd.DataFrame(pd.DataFrame(df.values.flatten().tolist()).values.reshape(2,-1), columns=idx) 
1000 loops, best of 3: 378 µs per loop 

%timeit pd.concat([pd.DataFrame(df[x].values.tolist()) for x in df.columns], axis=1,keys=df.columns) 
1000 loops, best of 3: 1.22 ms per loop 
+0

감사합니다. 그냥 더 빠른 해결책을 내놓았습니다 – Allen

+0

예, 항상'2' 열이 있습니까? 또한 OP는 MultiIndex를 열에 넣기를 원합니다. 어떻게 생각하십니까? – jezrael

+0

두 개 이상의 열에 대해서는 reshape()를 변경해야합니다. Multiindex를 보자. – Allen

관련 문제