在Python中,计算DataFrame中每列非零值的数量。

94
我有一个pandas DataFrame,其中第一列是"user_id",其余列是标签("Tag_0"到"Tag_122")。
我有以下格式的数据:
UserId  Tag_0   Tag_1
7867688 0   5
7867688 0   3
7867688 3   0
7867688 3.5 3.5
7867688 4   4
7867688 3.5 0

我的目标是为每个用户ID实现Sum(Tag)/Count(NonZero(Tags))df.groupby('user_id').sum()可以给我sum(tag),但是我对计算非零值的数量一无所知。
有没有可能用一条命令实现Sum(Tag)/Count(NonZero(Tags))
5个回答

175

我获取每列非零值的最喜欢方法是

df.astype(bool).sum(axis=0)

使用以下方法确定每行中非零元素的数量:

df.astype(bool).sum(axis=1)

(感谢Skulas)

如果您的数据框中存在NaN值,您应该先将它们替换为零,否则它们将被计算为1。

df.fillna(0).astype(bool).sum(axis=1)

(感谢SirC)


2
我认为你的意思是axis=0。 如果你使用axis=1,你将会计算非零 - Skulas
1
@skulas 很好的发现!我猜大多数人来这里是为了行,这就是为什么以前没有人抱怨 :) - The Unfun Cat
这是一个很棒的一行代码!可以获取所有非空列的值。 - Chandra Kanth
@Amir 日期类型会是零吗? - The Unfun Cat
2
如果你的数据框中有NaN,它们会对总和产生影响,这是很危险的。 - SirC
很好的发现,SirC!我会更新我的回答。 - The Unfun Cat

37
为什么不使用np.count_nonzero
  1. 要计算整个数据框中非零元素的数量,可以使用np.count_nonzero(df)
  2. 要计算所有行的非零元素的数量,可以使用np.count_nonzero(df, axis=0)
  3. 要计算所有列的非零元素的数量,可以使用np.count_nonzero(df, axis=1)

它也适用于日期。


4
谢谢您的回答!我最终采用了这个解决方案,因为我认为它很容易理解。我只做了两处修改:对于我理解的“获取所有行的非零值数量”(您的第二种情况),我需要使用axis=1而不是axis=0。并且我更喜欢将输出作为pandas.Series,所以我使用了result = pd.Series(index=df.index, data=np.count_nonzero(df, axis=1)) - marcu1000s

14

要计算非零值,只需执行(column!=0).sum(),其中column是您想要执行此操作的数据。 column != 0返回一个布尔数组,True为1,False为0,因此将其求和可以得到满足条件的元素数量。

因此,要获得所需结果,请执行

df.groupby('user_id').apply(lambda column: column.sum()/(column != 0).sum())

@BrenBram 如果某些单元格中有负值,应该采取什么方法? - Harsh Singal
@HarshSingal:column != 0将找到所有不为零的值,无论它们是正数还是负数。 - BrenBarn
抱歉没有准确地说明问题。 当我实施上述方法时,SUM(Tags)为负数的user_id在输出中返回-inf,而正数SUM(Tags)表现完美。 我一直无法弄清楚原因! - Harsh Singal
@HarshSingal:如果没有非零标签(即非零标签的计数为零),则可能会得到inf。对于这种情况,您的原始公式未定义,因此您需要考虑要得到什么结果。 - BrenBarn

0

我知道这个问题很老了,但似乎 OP 的目标与问题标题不同:

我的目标是为每个 user_id 实现 Sum(Tag)/Count(NonZero(Tags))...


针对 OP 的目的,我们可以将 0 替换为 NaN,并使用 groupby + mean(这是因为 mean 默认跳过 NaN):

out = df.replace(0, np.nan).groupby('UserId', as_index=False).mean()

输出:

    UserId  Tag_0  Tag_1
0  7867688    3.5  3.875

0

使用简单的列表推导式来获取df每列中非零值的计数:

[np.count_nonzero(df[x]) for x in df.columns]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接