如何使用 update() 方法对 Python Pandas Dataframe 中的 collection.Counter 个对象求和?
How can I sum collection.Counter objects in a Python Pandas Dataframe using the update() method?
我正在处理不完全适合 pandas 数据框的半结构化数据,因此我有一些列包含 collections.Counter 个长度差异很大的对象(即字典)。
我需要在另一列上应用 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 on 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:这种方法非常耗内存,不应该用于较大的数据集。
考虑字典列表 A
A = [{'A': 1,'B':-1,'C': 1},
{'A':-1,'B': 1, 'D': 0,'E': 1},
{'A': 0, 'E': 0,'F': 1},
{ 'B': 0,'C':-1, 'E':-1,'F':-1}]
pd.DataFrame(A).stack().groupby(level=1).sum().to_dict()
{'A{'A': 0.0, 'B': 0.0, 'C': 0.0, 'D': 0.0, 'E': 0.0, 'F': 0.0}
我会保留原来的答案。但这是基于我错误的假设,即您想要最后一个值。当我意识到 sum
就是您所需要的时,答案就演变了。
鉴于此,这是一个更好的解决方案
pd.DataFrame(A).sum().to_dict()
要将其直接应用到您定义的数据框 F
:
pd.concat([F.K, F.L.apply(pd.Series)], axis=1).groupby('K').sum()
我正在处理不完全适合 pandas 数据框的半结构化数据,因此我有一些列包含 collections.Counter 个长度差异很大的对象(即字典)。
我需要在另一列上应用 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 on 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:这种方法非常耗内存,不应该用于较大的数据集。
考虑字典列表 A
A = [{'A': 1,'B':-1,'C': 1},
{'A':-1,'B': 1, 'D': 0,'E': 1},
{'A': 0, 'E': 0,'F': 1},
{ 'B': 0,'C':-1, 'E':-1,'F':-1}]
pd.DataFrame(A).stack().groupby(level=1).sum().to_dict()
{'A{'A': 0.0, 'B': 0.0, 'C': 0.0, 'D': 0.0, 'E': 0.0, 'F': 0.0}
我会保留原来的答案。但这是基于我错误的假设,即您想要最后一个值。当我意识到 sum
就是您所需要的时,答案就演变了。
鉴于此,这是一个更好的解决方案
pd.DataFrame(A).sum().to_dict()
要将其直接应用到您定义的数据框 F
:
pd.concat([F.K, F.L.apply(pd.Series)], axis=1).groupby('K').sum()