使用pandas数据框的计数函数来过滤数据。

4

我有一个pandas数据框,我想通过应用基于count函数的过滤器创建一个新的数据框,以便仅选择那些计数等于指定数字的列。

例如,在下面的数据框中:

month_end   Col A       Col B       Col C       Col D
200703      NaN          NaN         NaN         NaN
200704      0.084       0.152       0.142      0.0766
200705      0.124       0.123       0.020       NaN 
200706      NaN         0.191       0.091       0.149   
200707      -0.136      0.047       0.135      -0.127

如果我的变量为4,则df1应该只包含Col B和Col D,以及索引month_end。
我该如何实现这个功能?

所以我首先的问题是:你先尝试了什么吗?数据框有一个count方法,它会给你一个系列,其中索引是列名,值是该列中非空结果的数量。 - Paul H
你能添加一个运行示例吗?这将展示给我们你的位置,并节省我们构建数据帧的麻烦。顺便说一下,澄清一下“计数”-我认为你想要非 NaN 值的计数,但要具体说明。 - tdelaney
是的,我有一定了解如何应用基于列的过滤器,但我不确定如何在所有列上应用计数函数以创建新的数据框。谢谢。 - Jamil
@tdelaney,是的,我想要根据非 NaN 值进行过滤。我已经在我的问题中添加了一张图片。希望这能让我的问题更容易理解。非常感谢您的回复。 - Jamil
@Jamil -- 它是 dataframe.count() - Paul H
3个回答

5
你可以按照以下思路进行操作:
df.loc[:,df.notna().sum(0).eq(4)]

    ColB   ColC
0    NaN    NaN
1  0.152  0.142
2  0.123  0.020
3  0.191  0.091
4  0.047  0.135

还有一个count,它在计数之前已经删除了重复项:

df.loc[:,df.count().eq(4)]

如果你想包含日期列,而它不是索引:

ix = df.notna().sum(0).eq(4)
df.loc[:,ix.index[ix].union(['month_end'])]

    ColB   ColC  month_end
0    NaN    NaN     200703
1  0.152  0.142     200704
2  0.123  0.020     200705
3  0.191  0.091     200706
4  0.047  0.135     200707

他可能也想返回日期列。 - Chris
1
@Chris 这个答案是正确的。如果 month_end "列" 实际上是索引,那么当 OP 在实际数据框上运行时,它将被包含在内。 - Paul H
1
我会使用.count()代替.notna().sum() - Paul H
是的,这不是我经常使用的一个,所以没有立刻想到。尽管如此,它还是符合答案的 :) @PaulH - yatu
1
感谢大家的快速帮助。看起来解决方案完美地运行了。通过观察数据框(df1),我可以看到行数较少的列已经被从数据框中删除了。我将对我的数据进行更详细的核对,但这看起来基本上已经解决了。再次感谢。 - Jamil

1
另一个不需要循环的解决方案:

s = df.notna().sum(0) == 4     
df = df.loc[:, s]

额,刚看到这个和上面的@yatu很相似 :-( - gtomer
1
非常感谢您的帮助。今天我学到了一些非常优雅的解决方案。再次感谢您。 - Jamil
当然。我是新来的(不太活跃)。今后我会记住这一点。非常感谢你。 - Jamil
1
作为以后的参考 @gtomer ,当用户意识到已经有相同的答案被发布时,他们往往会删除自己的答案。这样可以避免混淆是否答案是抄袭的(我相信不是这种情况),并且避免后一个答案被接受。另一个显而易见的原因是拥有两个相同的答案没有太多用处。 - yatu
@yatu - 试图删除它,但由于它已被"接受"而无法删除。抱歉。 - gtomer

0

使用for循环的解决方案:

for col in df.columns:
    if (df[col].count() != 4):
        df.drop(col, axis=1)

这里不需要写循环。 - Paul H
这不是必须的,但是可以选择。具体取决于@Jamil接下来的计划,可能是一个不错的选择。 - gtomer
但这样做是不对的。因为你没有保存 drop 的输出结果,所以它根本不会对原始数据进行操作。在 pandas 中循环很少是一个好选择。 - Paul H
谢谢大家的回复,但我希望有人能帮我找到更有效率的解决方案。谢谢。 - Jamil

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