2017-10-01 2 views
4

"표준화 된"것으로 설명 할 수있는 팬더 데이터 프레임이 있습니다. 디스플레이 목적으로 데이터를 "표준화 해제"하고 싶습니다. 즉, 출력 레코드에 같은 행을 넣으려는 여러 키 값에 일부 데이터를 분산시키고 자합니다. 일부 레코드는 결합 될 때 합계되어야합니다. (비공개 : 누군가가 "비정규 화"보다 더 좋은 용어를 가지고 있다면,이 질문을 편집하거나 주석에서 말하십시오.)Python Pandas : 한 데이터 프레임에서 다른 데이터 프레임으로 데이터 비정규 화

많은 열이있는 팬더 데이터 프레임으로 작업하고 있으므로 아래에 간단한 버전이 표시됩니다.

다음 코드는 (거의) 정규화 된 소스 데이터 프레임을 설정합니다. (두 번째 코드 블록에 대한 조언을 찾고 있는데,이 코드 블록은 컨텍스트를 제공하기위한 것입니다.) 실제 데이터와 유사하게 데이터를 식별하는 데 몇 가지 중복이 있으며 합계가되는 숫자가 있습니다.

import pandas as pd 

dates = pd.date_range('20170701', periods=21) 
datesA1 = pd.date_range('20170701', periods=11) 
datesB1 = pd.date_range('20170705', periods=9) 
datesA2 = pd.date_range('20170708', periods=10) 
datesB2 = pd.date_range('20170710', periods=11) 
datesC1 = pd.date_range('20170701', periods=5) 
datesC2 = pd.date_range('20170709', periods=9) 

cols=['Date','Type','Count'] 

df_A1 = pd.DataFrame({'Date':datesA1, 
         'Type':'Apples', 
         'Count': np.random.randint(30,size=11)}) 
df_A2 = pd.DataFrame({'Date':datesA2, 
         'Type':'Apples', 
         'Count': np.random.randint(30,size=10)}) 
df_B1 = pd.DataFrame({'Date':datesB1, 
         'Type':'Berries', 
         'Count': np.random.randint(30,size=9)}) 
df_B2 = pd.DataFrame({'Date':datesB2, 
         'Type':'Berries', 
         'Count': np.random.randint(30,size=11)}) 
df_C1 = pd.DataFrame({'Date':datesC1, 
         'Type':'Canteloupes', 
         'Count': np.random.randint(30,size=5)}) 
df_C2 = pd.DataFrame({'Date':datesC2, 
         'Type':'Canteloupes', 
         'Count': np.random.randint(30,size=9)}) 

frames = [df_A1, df_A2, df_B1, df_B2, df_C1, df_C2] 

dat_fra_source = pd.concat(frames) 

또한 다음 코드는 본인의 의도를 실현합니다. 원본 데이터 프레임에는 날짜 및 과일 유형 (A, B 및 C)마다 여러 행이 있습니다. 대상 데이터는 A, B의 합계로, 하루에 하나의 행을 가지고 있으며, C.

dat_fra_dest = pd.DataFrame(0, index=dates, columns=['Apples','Berries','Canteloupes']) 

for index,row in dat_fra_source.iterrows(): 
    dat_fra_dest.at[row['Date'],row['Type']]+=row['Count'] 

이 할 수있는 청소기 방법이 있는지 내 질문은 : 제로를 필요로하지 않는 방법 - 초기화 및/또는 라인 단위가 아닌 전체 데이터 프레임에서 작동하는 방식. 또한 효율적인 구현 방법에 대해 회의적입니다. 또한 단순화 된 예제에서 "개수"만 다루는 동안 실제 예제에는 추가 열이 있습니다. A, B, C의 경우 카운트뿐만 아니라 체중과 볼륨도 있다고 생각하십시오.

+0

나는 매우 비슷한 일을 할 - 당신이 1-3 가장 편리하다고 아래의 옵션이있는 어떤 조언을해야합니까? – goose

답변

5

옵션 1

dat_fra_source.groupby(['Date','Type']).sum().unstack().fillna(0) 

Out[63]: 
      Count      
Type  Apples Berries Canteloupes 
Date         
2017-07-01 13.0  0.0  24.0 
2017-07-02 18.0  0.0  16.0 
2017-07-03 11.0  0.0  29.0 
2017-07-04 13.0  0.0   7.0 
2017-07-05 24.0 11.0  23.0 
2017-07-06 6.0  4.0   0.0 
2017-07-07 29.0 26.0   0.0 
2017-07-08 31.0 19.0   0.0 
2017-07-09 38.0 17.0  26.0 
2017-07-10 57.0 54.0   1.0 
2017-07-11 4.0 41.0  10.0 
2017-07-12 16.0 28.0  23.0 
2017-07-13 25.0 20.0  20.0 
2017-07-14 19.0  6.0  15.0 
2017-07-15 6.0 22.0   7.0 
2017-07-16 16.0  0.0   5.0 
2017-07-17 29.0  7.0   4.0 
2017-07-18 0.0 21.0   0.0 
2017-07-19 0.0 19.0   0.0 
2017-07-20 0.0  8.0   0.0 

옵션 2

pd.pivot_table(dat_fra_source,index=['Date'],columns=['Type'],values='Count',aggfunc=sum).fillna(0) 
Out[75]: 
Type  Apples Berries Canteloupes 
Date          
2017-07-01 13.0  0.0   24.0 
2017-07-02 18.0  0.0   16.0 
2017-07-03 11.0  0.0   29.0 
2017-07-04 13.0  0.0   7.0 
2017-07-05 24.0  11.0   23.0 
2017-07-06  6.0  4.0   0.0 
2017-07-07 29.0  26.0   0.0 
2017-07-08 31.0  19.0   0.0 
2017-07-09 38.0  17.0   26.0 
2017-07-10 57.0  54.0   1.0 
2017-07-11  4.0  41.0   10.0 
2017-07-12 16.0  28.0   23.0 
2017-07-13 25.0  20.0   20.0 
2017-07-14 19.0  6.0   15.0 
2017-07-15  6.0  22.0   7.0 
2017-07-16 16.0  0.0   5.0 
2017-07-17 29.0  7.0   4.0 
2017-07-18  0.0  21.0   0.0 
2017-07-19  0.0  19.0   0.0 
2017-07-20  0.0  8.0   0.0 

그리고 당신은 열 권 무게

dat_fra_source['vol']=2 
dat_fra_source['weight']=2 
dat_fra_source.groupby(['Date','Type']).apply(lambda x: sum(x['vol']*x['weight']*x['Count'])).unstack().fillna(0) 
Out[88]: 
Type  Apples Berries Canteloupes 
Date          
2017-07-01 52.0  0.0   96.0 
2017-07-02 72.0  0.0   64.0 
2017-07-03 44.0  0.0  116.0 
2017-07-04 52.0  0.0   28.0 
2017-07-05 96.0  44.0   92.0 
2017-07-06 24.0  16.0   0.0 
2017-07-07 116.0 104.0   0.0 
2017-07-08 124.0  76.0   0.0 
2017-07-09 152.0  68.0  104.0 
2017-07-10 228.0 216.0   4.0 
2017-07-11 16.0 164.0   40.0 
2017-07-12 64.0 112.0   92.0 
2017-07-13 100.0  80.0   80.0 
2017-07-14 76.0  24.0   60.0 
2017-07-15 24.0  88.0   28.0 
2017-07-16 64.0  0.0   20.0 
2017-07-17 116.0  28.0   16.0 
2017-07-18  0.0  84.0   0.0 
2017-07-19  0.0  76.0   0.0 
2017-07-20  0.0  32.0   0.0 
2

사용 pd.crosstab이 가정 :

pd.crosstab(dat_fra_source['Date'], 
      dat_fra_source['Type'], 
      dat_fra_source['Count'], 
      aggfunc='sum', 
      dropna=False).fillna(0) 

출력 :

Type  Apples Berries Canteloupes 
Date          
2017-07-01 19.0  0.0   4.0 
2017-07-02 25.0  0.0   4.0 
2017-07-03 11.0  0.0   26.0 
2017-07-04 27.0  0.0   8.0 
2017-07-05  8.0  18.0   12.0 
2017-07-06 10.0  11.0   0.0 
2017-07-07  6.0  17.0   0.0 
2017-07-08 10.0  5.0   0.0 
2017-07-09 51.0  25.0   16.0 
2017-07-10 31.0  23.0   21.0 
2017-07-11 35.0  40.0   10.0 
2017-07-12 16.0  30.0   9.0 
2017-07-13 13.0  23.0   20.0 
2017-07-14 21.0  26.0   27.0 
2017-07-15 20.0  17.0   19.0 
2017-07-16 12.0  4.0   2.0 
2017-07-17 27.0  0.0   5.0 
2017-07-18  0.0  5.0   0.0 
2017-07-19  0.0  26.0   0.0 
2017-07-20  0.0  6.0   0.0 
+1

lol :) nice one +1 – Wen

+0

@Wen ... 계속 진행하십시오. –

+0

nope. 나는 그것을 찾는다. pd.crosstab이 aggfunc을 가질 수 있다는 것을 모른다. 새로운 것을 배우자! 그것을 유지하십시오 :) – Wen

관련 문제