如何计算 groupby 对象中包含的多个列表并将该组列表中的每个值的计数相加
Posted
技术标签:
【中文标题】如何计算 groupby 对象中包含的多个列表并将该组列表中的每个值的计数相加【英文标题】:How to count through several lists contained in a groupby object and add counts together for every value in the lists of that group 【发布时间】:2016-01-14 23:21:20 【问题描述】:我有以下问题。我有一个数据框,我将groupby
列为一列,然后将strings
的list
包含在另一列中。由于它是分组的,因此我有来自组中多个列的多个列表。现在我想遍历组中的每个列表并计算这些列表中包含的值。最后,对于每个值,我创建一个新列,并希望它包含该组中每个列表中值的总计数。这是我的示例数据框:
df1:
Column1 Column2
0 L17 a,b,c,d,e
1 L7 a,b,c
2 L6 a,b,f
3 L6 a,b,e
我想出来的是:
Column1 Column2 a b c d e f h
0 L17 a,b,c,d,e 1 1 1 1 1 nan nan
1 L7 a,b,c 1 1 1 nan nan nan nan
2 L6 a,b,f 2 2 nan nan 1 1 nan
到目前为止,我编写的代码是:
def NewCols(x):
for key, group in UngroupedResGenesLineage.groupby('Column1'):
for item, frame in group['Column2'].iteritems():
Genes = frame.split(',')
counter = collections.Counter(Genes)
for value in Genes:
string = value
x[string] = sum(counter.values())
return x
X = df1.groupby('Column1').apply(NewCols)
到目前为止,该代码的工作原理是我获得了新列和组中包含的所有值的列表。问题是它们都填充了相同的值,这绝对是不正确的。我最近才发现 Counter
并认为它可能有用,但我不知道如何计算一个组的所有 frame
列表(代码中的“基因”)中的所有值并将每个值加在一起列表中的值。
有人知道我应该如何更改我的代码以实现我想要的吗?提前致谢!
【问题讨论】:
为什么L6
e
没有 1
?结果你还需要Column2
?
哦,我的错。在L6
e
应该有1
,在问题中修复它。是的,Column2
应该保留在数据框中。
对于 L6,您不想将两行的 Column2 组合起来吗?
是的,这正是我想要得到的!
【参考方案1】:
如果在生成的 DataFrame 中,您需要 Column2
的所有行中的组合(唯一元素)。然后您可以使用以下函数,该函数使用 Counter 计算所有元素并从 Column2 中的元素创建新列。示例 -
def func(row):
slist = np.array(row['Column2'].str.split(',').tolist()).flatten()
count = Counter(slist)
res = pd.Series()
res['Column2'] = ','.join(sorted(count))
for key,val in count.items():
res[key] = val
return pd.DataFrame(res).T
然后你可以分组然后重置索引。示例 -
result = df.groupby('Column1').apply(func).reset_index().drop('level_1',axis=1)
演示 -
In [130]: def func(row):
.....: slist = np.array(row['Column2'].str.split(',').tolist()).flatten()
.....: count = Counter(slist)
.....: res = pd.Series()
.....: res['Column2'] = ','.join(sorted(count))
.....: for key,val in count.items():
.....: res[key] = val
.....: return pd.DataFrame(res).T
.....:
In [131]: df
Out[131]:
Column1 Column2
0 L17 a,b,c,d,e
1 L7 a,b,c
2 L6 a,b,f
3 L6 a,b,e
In [135]: df.groupby('Column1').apply(func).reset_index().drop('level_1',axis=1)
Out[135]:
Column1 Column2 a b c d e f
0 L17 a,b,c,d,e 1 1 1 1 1 NaN
1 L6 a,b,e,f 2 2 NaN NaN 1 1
2 L7 a,b,c 1 1 1 NaN NaN NaN
【讨论】:
看起来很流畅,但实际上当我尝试运行它时,我得到:TypeError: unhashable type: 'list'
。知道什么可能导致该错误吗?
它从我开始 df.groupby 的那一行开始,最终缩小到553 self_get = self.get 554 for elem in iterable: --> 555 self[elem] = self_get(elem, 0) + 1 556 if kwds: 557 self.update(kwds) TypeError: unhashable type: 'list'
从我发布的代码看来不像,很可能是您自己的代码?
不,它来自您的代码。我会发布整个错误消息,但它太 lnog 无法发表评论...---> 11 UngroupedResGenesLineage.groupby('Lineage').apply(func).reset_index().drop('level_1',axis=1) C:\Users\user\Anaconda\lib\site-packages\pandas\core\groupby.pyc in apply(self, func, *args, **kwargs) 669 # ignore SettingWithCopy here in case the user mutates 670 with option_context('mode.chained_assignment',None): --> 671 return self._python_apply_general(f) 672 673 def _python_apply_general(self, f):
如果有帮助将成为其中的一部分..
也许你可以截个图并上传并链接到它【参考方案2】:
您可以使用pandas str.get_dummies
In[3]: cntr = df.Column2.str.get_dummies(',').groupby(df.Column1).sum()
In[4]: print cntr
a b c d e f
Column1
L17 1 1 1 1 1 0
L6 2 2 0 0 1 1
L7 1 1 1 0 0 0
现在,您可以将其与原始数据框连接起来,并将 0 替换为 nan。
In[5]: x = pd.merge(df.drop_duplicates('Column1'), cntr.replace(0, pd.np.nan).reset_index())
In[6]: print x
Column1 Column2 a b c d e f
0 L17 a,b,c,d,e 1 1 1 1 1 NaN
1 L7 a,b,c 1 1 1 NaN NaN NaN
2 L6 a,b,f 2 2 NaN NaN 1 1
【讨论】:
简单快捷,谢谢!我将阅读.get_dummies
函数。
等等,实际上它不能正常工作..我在合并中出了点问题。我想这与索引有关,因为 cntr 的索引是Column1
,另一个是int64
。我将研究如何将int64
索引添加到 cntr 数据帧。以上是关于如何计算 groupby 对象中包含的多个列表并将该组列表中的每个值的计数相加的主要内容,如果未能解决你的问题,请参考以下文章
在 C# 中,如何使用反射计算表达式主体输出函数中包含的属性数量?