2017-04-21 5 views
2

두 개의 데이터 프레임이 있습니다. 하나는 각 하위 포트폴리오에 대한 값이 있고 다른 하나는이 하위 포트폴리오가 롤업하는 상위 수준 포트폴리오 목록이 있습니다.Python pandas - 하위 포트폴리오 집계

table1 
subportfolio value 
top-alpha-1 1 
top-alpha-2 2 
top-alpha-3 3 
top-beta-1 4 
top-beta-2 5 
top-beta-3 6 
top-gamma-1 7 
top-gamma-2 8 
top-gamma-3 9 

table2 
portfolio parent  level 
top-alpha-1 top-alpha 1 
top-alpha-2 top-alpha 1 
top-alpha-3 top-alpha 1 
top-beta-1 top-beta 1 
top-beta-2 top-beta 1 
top-beta-3 top-beta 1 
top-gamma-1 top-gamma 1 
top-gamma-2 top-gamma 1 
top-gamma-3 top-gamma 1 
top-alpha top  2 
top-beta  top  2 
top-gamma top  2 
top   self  3 

내 목표는뿐만 아니라 subportfolios이 값으로 채워하지만, 모든 높은 수준의 그들 아래의 포트폴리오의 집계에 따라 값을 할당받을 있도록, 어떤 방법으로이 두 테이블을 병합하는 것입니다.

첫 번째 생각은 일종의 반복 이었지만 많은 양의 데이터 때문에 시간이 많이 걸릴 수있었습니다.

table2 
portfolio value parent  level 
top-alpha-1 1  top-alpha 1 
top-alpha-2 2  top-alpha 1 
top-alpha-3 3  top-alpha 1 
top-beta-1 4  top-beta 1 
top-beta-2 5  top-beta 1 
top-beta-3 6  top-beta 1 
top-gamma-1 7  top-gamma 1 
top-gamma-2 8  top-gamma 1 
top-gamma-3 9  top-gamma 1 
top-alpha 6  top  2 
top-beta  15 top  2 
top-gamma 24 top  2 
top   45 self  3 

답변

0

감사를 실행합니다. 난 당신이 모두 나에게 준 아이디어를 도난 및 (레벨의 수, 포트폴리오에 대한 서식 등)

df = table2.merge(table1, on="portfolio", how="left") 
for i in range(2,df.level.max()+1): 
    df1 = df.loc[df.level==i-1,:].groupby('parent', 
      as_index=False).sum().rename(columns= 
      {"parent":"portfolio"}).set_index('portfolio') 
    df = df.set_index('portfolio').combine_first(df1).reset_index() 

내가 사용 가능한 동적 무언가를 구축하기 위해 노력했습니다 그의 대답에 piRsquared가 제공 한 'setup'. 결과 : 당신이 순서대로 포트폴리오를 유지하려면

 portfolio level  parent value 
0   top  3  self 45.0 
1  top-alpha  2  top 6.0 
2 top-alpha-1  1 top-alpha 1.0 
3 top-alpha-2  1 top-alpha 2.0 
4 top-alpha-3  1 top-alpha 3.0 
5  top-beta  2  top 15.0 
6 top-beta-1  1 top-beta 4.0 
7 top-beta-2  1 top-beta 5.0 
8 top-beta-3  1 top-beta 6.0 
9  top-gamma  2  top 24.0 
10 top-gamma-1  1 top-gamma 7.0 
11 top-gamma-2  1 top-gamma 8.0 
12 top-gamma-3  1 top-gamma 9.0 

, 당신이 사용할 수있는

df = df.sort_values('level') 
3

새 응답

참고 : 나는 'portfolio'

def agg_lvl(t1, t2): 
    lcol = ['level', 'portfolio'] 
    rcol = ['parent', 'portfolio'] 
    kwargs = dict(
     left_on='portfolio', right_on='parent', 
     suffixes=['_', ''] 
    ) 
    lvl = t2[lcol].merge(t2[rcol], **kwargs).drop('portfolio_', 1).merge(t1) 
    lvl = lvl.groupby('parent').value.sum().rename_axis('portfolio').reset_index() 
    return t1.append(lvl, ignore_index=True).drop_duplicates(), t2 

o1, o2 = agg_lvl(*agg_lvl(table1, table2)) 

o2.merge(o1) 

    level  parent portfolio value 
0  1 top-alpha top-alpha-1  1 
1  1 top-alpha top-alpha-2  2 
2  1 top-alpha top-alpha-3  3 
3  1 top-beta top-beta-1  4 
4  1 top-beta top-beta-2  5 
5  1 top-beta top-beta-3  6 
6  1 top-gamma top-gamma-1  7 
7  1 top-gamma top-gamma-2  8 
8  1 top-gamma top-gamma-3  9 
9  2  top top-alpha  6 
10  2  top  top-beta  15 
11  2  top top-gamma  24 
12  3  self   top  45 

설정

에 열 이름 'subportfolio' 변경 6,
table2 = pd.DataFrame({ 
     'level': [1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3], 
     'parent': [ 
      'top-alpha', 
      'top-alpha', 
      'top-alpha', 
      'top-beta', 
      'top-beta', 
      'top-beta', 
      'top-gamma', 
      'top-gamma', 
      'top-gamma', 
      'top', 
      'top', 
      'top', 
      'self'], 
     'portfolio': [ 
      'top-alpha-1', 
      'top-alpha-2', 
      'top-alpha-3', 
      'top-beta-1', 
      'top-beta-2', 
      'top-beta-3', 
      'top-gamma-1', 
      'top-gamma-2', 
      'top-gamma-3', 
      'top-alpha', 
      'top-beta', 
      'top-gamma', 
      'top']}) 

table1 = pd.DataFrame({ 
     'portfolio': ['top-alpha-1', 'top-alpha-2', 'top-alpha-3', 'top-beta-1', 'top-beta-2', 'top-beta-3', 'top-gamma-1', 'top-gamma-2', 'top-gamma-3'], 
     'value': [1, 2, 3, 4, 5, 6, 7, 8, 9] 
    }) 

된 대답

이 솔루션은 내 다른 솔루션을 활용하고 정확하게 당신이 필요하지 않을 수 있습니다 ...하지만 다시, 당신은 당신이 필요로 정확히 분명히하지 않았다. 그래서 몇 가지 자유를 취했습니다

먼저 subportfolio 열을 '-'으로 나눈 다른 데이터 프레임 df을 만들었습니다.

col = 'subportfolio' 
rnm_dict = dict(enumerate(list('321'))) 
df = table1.drop(col, 1).join(table1[col].str.split('-', expand=True).rename(columns=rnm_dict)) 
print(df) 

    value 3  2 1 
0  1 top alpha 1 
1  2 top alpha 2 
2  3 top alpha 3 
3  4 top beta 1 
4  5 top beta 2 
5  6 top beta 3 
6  7 top gamma 1 
7  8 top gamma 2 
8  9 top gamma 3 

지금 집계 모든 답변에 대한

agged = pd.concat([ 
     df.assign(
      **{x: '' for x in '321'[i:]} 
     ).groupby(list('321')).sum() for i in range(1, 4) 
    ]).sort_index() 


table2.join(agged.set_index(agged.index.to_series().str.join('-').str.strip('-').values), on='portfolio') 

    level  parent portfolio value 
0  1 top-alpha top-alpha-1  1 
1  1 top-alpha top-alpha-2  2 
2  1 top-alpha top-alpha-3  3 
3  1 top-beta top-beta-1  4 
4  1 top-beta top-beta-2  5 
5  1 top-beta top-beta-3  6 
6  1 top-gamma top-gamma-1  7 
7  1 top-gamma top-gamma-2  8 
8  1 top-gamma top-gamma-3  9 
9  2  top top-alpha  6 
10  2  top  top-beta  15 
11  2  top top-gamma  24 
12  3  self   top  45 
2
table3 = table2.merge(table1, 
         left_on="portfolio", 
         right_on="subportfolio", 
         how="left").drop('subportfolio', axis=1) 
table3['letter'] = table3.portfolio.str.split('-').str[1] 
table3.loc[table3.level==2, 'value'] = table3.groupby('letter').value.sum().values 
table3.loc[table3.level==3, 'value'] = table3.loc[table3.level==2, 'value'].sum() 
table3.drop('letter', axis=1, inplace=True) 

# output 
     portfolio  parent level value 
0 top-alpha-1 top-alpha  1 1.0 
1 top-alpha-2 top-alpha  1 2.0 
2 top-alpha-3 top-alpha  1 3.0 
3 top-beta-1 top-beta  1 4.0 
4 top-beta-2 top-beta  1 5.0 
5 top-beta-3 top-beta  1 6.0 
6 top-gamma-1 top-gamma  1 7.0 
7 top-gamma-2 top-gamma  1 8.0 
8 top-gamma-3 top-gamma  1 9.0 
9  top-alpha  top  2 6.0 
10  top-beta  top  2 15.0 
11 top-gamma  top  2 24.0 
12   top  self  3 45.0