【发布时间】:2016-08-10 08:22:37
【问题描述】:
我正在处理不完全适合 pandas 数据框的半结构化数据,因此我有一些列包含长度差异很大的集合。计数器对象(即字典)。
我需要在另一列上应用 groupby 并且需要对这些计数器求和,但是不要删除零或忽略负值。这意味着我不能在这些列上使用 sum() 方法。
选择的方法是 update() 方法,但它不能像 sum() 方法那样简单地应用,因为它需要一个参数,该参数是另一个 Counter,但它位于另一行而不是另一列。
例子:
import pandas as pd
import collections as cc
A = [cc.Counter({'A': 1,'B':-1,'C': 1}),\
cc.Counter({'A':-1,'B': 1, 'D': 0,'E': 1}),\
cc.Counter({'A': 0, 'E': 0,'F': 1}),\
cc.Counter({ 'B': 0,'C':-1, 'E':-1,'F':-1})]
B = ['N','N','N','N']
S1 = pd.Series(B,index=['W','X','Y','Z'],name='K',dtype=str)
S2 = pd.Series(A,index=['W','X','Y','Z'],name='L',dtype=dict)
F = pd.merge(S1.to_frame(),S2.to_frame(),left_index=True,right_index=True)
print F
这导致输出
K L
W N {u'A': 1, u'C': 1, u'B': -1}
X N {u'A': -1, u'B': 1, u'E': 1, u'D': 0}
Y N {u'A': 0, u'E': 0, u'F': 1}
Z N {u'C': -1, u'B': 0, u'E': -1, u'F': -1}
这样做:
G = F.groupby('K')
print G.sum()
导致这个输出:
L
K
N {}
但我想要的是这样的:
Counter({'A': 0, 'C': 0, 'B': 0, 'E': 0, 'D': 0, 'F': 0})
可以通过如下的更新方法手动完成:
for i in range(1,4):
A[0].update(A[i])
print A[0]
所以我要么需要一种技术来将 update() 应用于 groupby 对象,要么通过创建适当的函数,要么将分组的行更改为列(这似乎相当低效且耗时),或者我将拥有以忽略计数器中的零和负值的方式重组我的数据。
欢迎提出任何想法。
编辑: 在我的示例中,我仍然无法将建议的解决方案应用于分组 DataFrame:
G.apply(lambda x: pd.DataFrame(x).sum().to_dict())
给出结果:
K
N {u'K': u'NNNN', u'L': {}}
dtype: object
问题是我不太明白 apply 在 groupby 对象上的工作原理。
就像我这样做的时候:
F.groupby('K').apply(lambda x: list(x))
结果是:
K
N [K, L]
dtype: object
我不明白为什么以及如何。
编辑 2(解决方案):
在@piRSquared 的回答帮助我解决了问题后,我添加了完整的解决方案,不仅可以获取字典,还可以将字典重新放入 DataFrame:
pd.DataFrame.from_dict([to_dict_dropna(pd.concat([F.K, F.L.apply(pd.Series)], axis=1)\
.groupby('K').sum())]).T.reset_index()
to_dict_dropna() 函数取自“make pandas DataFrame to a dict and dropna”,如果求和字典中有没有值的键,则该函数是必需的。 我正在转置框架并重置索引,因为我需要将初始索引作为列。然后我将它与其他帧合并以获得我需要的最终格式。
PS:这种方法非常消耗内存,不应该用于更大的数据集。
【问题讨论】:
-
'C'的最终值不应该是-1吗?以及'E'和'F'?
标签: python python-2.7 pandas dataframe counter