Pandas按字典提供的数据帧特定行

时间:2017-07-26 15:36:16

标签: python pandas join dataframe merge

我有一个包含一列键和其他一些列的数据框。我想合并(sum)数据帧的特定行。应该将哪些行相加在一起由字典提供。此映射由{key:[list of other keys]}的字典提供。

具体来说,这是一些示例代码:

data = [('A', 4, 10),
        ('B', 7, 10),
        ('C', 3, 9)]
labels = ['Key','Col1','Col2']
mydf = pd.DataFrame(data,columns=labels)

idx_grouping_dict = { 'A' : ['C'], 'B' : ['A'], 'C' : ['A', 'B']}


desired_result = pd.DataFrame(
        [('A', 7, 19),
         ('B', 11, 20),
         ('C', 14, 29)], columns=labels)

这里,索引为' A'被添加到具有索引' C'的行,具有索引的行' B'被添加到具有索引' A'的行,以及具有索引' C'的行被添加到两行' A'和' B'。

我确定有办法做到这一点!也许形成某种临时数据帧并使用聪明的内部或外部联接?我很难过。

3 个答案:

答案 0 :(得分:4)

您可以使用键和值作为两个单独的列从字典创建数据框,将其与mydf连接,然后按键列(来自原始字典)和总和列分组:

pd.DataFrame([(g, k) for g, ks in idx_grouping_dict.items() for k in ks + [g]], 
             columns=["GKey", "Key"]).merge(mydf).groupby("GKey", as_index=False).sum()

#GKey   Col1    Col2
#0  A      7      19
#1  B     11      20
#2  C     14      29
keydf = pd.DataFrame([(g, k) for g, ks in idx_grouping_dict.items() for k in ks + [g]], columns=["GKey", "Key"])

keydf
#GKey   Key
#0  C     A
#1  C     B
#2  C     C
#3  B     A
#4  B     B
#5  A     C
#6  A     A

keydf.merge(mydf)

#GKey Key Col1 Col2
#0  C   A    4   10
#1  B   A    4   10
#2  A   A    4   10
#3  C   B    7   10
#4  B   B    7   10
#5  C   C    3    9
#6  A   C    3    9

keydf.merge(mydf).groupby('GKey', as_index=False).sum()

#GKey   Col1    Col2
#0  A      7      19
#1  B     11      20
#2  C     14      29

另一种选择:

val_df = mydf.set_index("Key")
pd.DataFrame.from_dict({g: val_df.loc[[g] + ks].sum() for g, ks in idx_grouping_dict.items()}, orient="index")

# Col1  Col2
#A   7    19
#B  11    20
#C  14    29

时序

%%timeit
val_df = mydf.set_index("Key")
pd.DataFrame.from_dict({g: val_df.loc[[g] + ks].sum() for g, ks in idx_grouping_dict.items()}, orient="index")
# 100 loops, best of 3: 2.51 ms per loop

%timeit pd.DataFrame([(g, k) for g, ks in idx_grouping_dict.items() for k in ks + [g]], columns=["GKey", "Key"]).merge(mydf).groupby("GKey", as_index=False).sum()
# 100 loops, best of 3: 3.22 ms per loop

答案 1 :(得分:3)

这是一个(略微)较慢的解决方案,它涉及首先转置数据帧,然后在转置它之前执行列式求和。

# https://stackoverflow.com/a/45332338/4909087
In [457]: temp = mydf.T.rename_axis(None, axis=1)

In [456]: pd.DataFrame({k : temp[[k]].join(temp[[i for i in v]]).agg('sum', axis=1) for k, v in idx_grouping_dict.items()}).T
Out[456]: 
   Col1  Col2
A     7    19
B    11    20
C    14    29

答案 2 :(得分:1)

我的解决方案基于Dataframe ..

idx_grouping_dict = { 'A' : ['C'], 'B' : ['A'], 'C' : ['A', 'B']}
s = pd.DataFrame(pd.Series(idx_grouping_dict, name='Va'))
s.apply(lambda x: x['Va'].append(x.name), axis=1)
Temp_unnest = pd.DataFrame([[i, x]
              for i, y in s['Va'].apply(list).iteritems()
                  for x in y], columns=list('IV'))
data = [('A', 4, 10),
        ('B', 7, 10),
        ('C', 3, 9)]
labels = ['Key','Col1','Col2']
mydf = pd.DataFrame(data,columns=labels)
Temp_unnest=Temp_unnest.merge(mydf,left_on='V',right_on='Key',how='left')
Temp_unnest.groupby('I').sum()


   Col1  Col2
I            
A     7    19
B    11    20
C    14    29