首页 > 解决方案 > 逐行条件计数保持所有列而不迭代数据帧

问题描述

我正在努力解决熊猫的条件计数问题。

问题

我有一个熊猫数据框,它有 4 列(为了这个例子):“id”、“id2”、“col1”和“type”。类型栏可以有 3 个值,即“A”、“B”和“C”。我想做的是,对于每一行,计算具有相同 id 和 id2 的类型 C 的数量。这是一个示例数据框:

    id   id2 col1 type
0   "e"  "z"   0   "A"
1   "e"  "z"   1   "C"
2   "e"  "z"   2   "C"
3   "e"  "y"   3   "C"
4   "e"  "y"   4   "A"  
5   "f"  "y"   4   "A"
6   "f"  "x"   3   "B"
7   "f"  "x"   4   "B"
8   "g"  "w"   5   "C"
9   "g"  "w"   6   "B"

构建示例数据框的代码:

pd.DataFrame({
    "id":   ["e", "e", "e", "e", "e", "f", "f", "f", "g", "g"],
    "id2":  ["z", "z", "z", "y", "y", "x", "x", "x", "w", "w"],
    "col1": [ 0 ,  1 ,  2 ,  3 ,  4 ,  4 ,  3 ,  4 ,  5 ,  6 ],
    "type": ["A", "C", "C", "C", "A", "A", "B", "B", "C", "B"]
})

和期望的结果:

    id   id2 col1 type  count
0   "e"  "z"   0   "A"    2
1   "e"  "z"   1   "C"    2
2   "e"  "z"   2   "C"    2 
3   "e"  "y"   3   "C"    1
4   "e"  "y"   4   "A"    1
5   "f"  "y"   4   "A"    0
6   "f"  "x"   3   "B"    0
7   "f"  "x"   4   "B"    0
8   "g"  "w"   5   "C"    1
9   "g"  "w"   6   "B"    1

我真的不关心类型为“C”的行(例如第 1、2、3、8 行)会发生什么,所以如果它们没有出现在结果数据框中,这不是问题。

我想要一个不依赖于通过数据集迭代“我自己”的解决方案(没有应用或 for 循环),因为它们太慢了。我希望找到一种解决问题的“流行”方法。

注意:在“真实”数据集中有 3 列用于索引,类型可以有 5 个不同的值,应保留 36 个数据列。但我更喜欢可扩展的解决方案,不受这些数字的限制。

我试过的

我可以使用 sqlalchemy 和查询来解决问题。实际上,结果应该与以下查询匹配:

SELECT a.*, (SELECT COUNT(*)
             FROM df b
             WHERE 
                 b.id  = a.id  AND
                 b.id2 = a.id2 AND
                 b.type = "C")
FROM df a

最初的问题也可以改写为“与此查询等效的 python 代码是什么?”。

我也可以使用 apply 来解决问题。由于数据集的大小,两者都非常慢,尽管 sql 方法可能很慢,因为它首先必须构建数据库。

相关文章

这篇文章几乎解决了这个问题,但不适用于外部数据列或多个索引,我无法将它们用于我的示例。

这条线接近我正在寻找的,唯一的问题是它只保留你分组的列:

df.groupby(["id", "id2", "type"]).size().unstack().reset_index()

如果缺少任何信息,请告诉我。感谢您花时间阅读我的帖子,并为拼写错误感到抱歉!

标签: pythonpandas

解决方案


试试这个:

answer = df.groupby(['id','id2']).transform(sum)['type'].str.count('C')
pd.concat([df,answer], axis=1)

  id id2  col1  type  type
0  e   z     0     A     2
1  e   z     1     C     2
2  e   z     2     C     2
3  e   y     3     C     1
4  e   y     4     A     1
5  f   x     4     A     0
6  f   x     3     B     0
7  f   x     4     B     0
8  g   w     5     C     1
9  g   w     6     B     1

您可以将 groupby 中的列增加到您希望的任何/多少。


推荐阅读