提问人:24n8 提问时间:11/16/2023 最后编辑:Goku - stands with Palestine24n8 更新时间:11/17/2023 访问量:99
如何检查数据帧是否包含所有 0 个条目?
How to check that a dataframe consists of all 0 entries?
问:
我知道一种方法是遍历所有列,例如,
for col in df.columns:
assert (df[col] != 0).sum() == 0
有没有更好的方法可以对整个数据帧进行操作,而无需遍历每个单独的列?
答:
1赞
kevin41
11/16/2023
#1
如果 df 中的所有值都为 0,则此函数将返回,如果不是。True
False
def is_zero(df):
vals = df.to_numpy()
return (0 == vals).all()
评论
0赞
Mark
11/16/2023
我想知道你是否能做到没有to_numpy()
-> (df == 0).all(axis=None)
0赞
kevin41
11/16/2023
看起来你可以,@Goku发布了不少选项
0赞
Nick
11/16/2023
我已经在另一篇文章中发布了您(和其他答案)的计时结果。
0赞
Nick
11/16/2023
有趣的是,事实证明使用是一件好事to_numpy
0赞
24n8
11/16/2023
@Nick 也许numpy's比pandas更优化?all
1赞
Goku - stands with Palestine
11/16/2023
#2
正如 @Mark 所评论的那样:
您可以尝试:
(df == 0).all()
#output
Col_1 True
Col_2 True
dtype: bool
它将给出单个列的结果,就像所有列一样; 都是Col_1
0
Col_2
0
如果你这样做:
(df == 0).all(axis=None)
它将提供整个数据帧
您还可以执行以下操作:
all((df == 0).all())
评论
0赞
Nikolaj Š.
11/16/2023
使用要好得多,因为它会返回第一个非零元素(如果有的话),就像@tdelaney的答案一样not any()
0赞
Nick
11/16/2023
我已经在另一篇文章中发布了您(和其他答案)的计时结果。
1赞
Riyan Sthefanus Nainggolan
11/16/2023
#3
看看这个:
df.isin([0]).sum()
1赞
tdelaney
11/16/2023
#4
您可以检查是否有任何内容不是 0,然后否定。使用带有轴 None 的 dataFrame 方法检查所有值。这应该在第一个非零值上停止,该值优于或将构建一个全新的序列或数据帧。.any
sum
df == 0
not df.any(axis=None)
评论
1赞
Nick
11/16/2023
我已经在另一篇文章中发布了您(和其他答案)的计时结果。
3赞
Nick
11/16/2023
#5
出于好奇,我测试了这里给出的答案中的方法,我在 StackOverflow 的其他地方发现了类似的问题。以下是方法:
funcs = {
'tdelaney' : lambda df:not df.any(axis=None),
'Goku 1' : lambda df:(df == 0).all(axis=None),
'Goku 2' : lambda df:all((df == 0).all()),
'kevin41' : lambda df:(0 == df.to_numpy()).all(),
'other 1' : lambda df:not np.any(df),
'other 2' : lambda df:(df != 0).sum().sum() == 0,
'other 3' : lambda df:(df != 0).any(axis=None)
}
为了进行测试,我使用了 1000 行和 1000 列的数据帧,其中全是零,另外三个值分别为 和 :1
[1,1]
[499,499]
[999,999]
N = 1000
df0 = pd.DataFrame(np.zeros([N,N]))
df_low = pd.DataFrame(np.zeros([N,N]))
df_mid = pd.DataFrame(np.zeros([N,N]))
df_high = pd.DataFrame(np.zeros([N,N]))
df_low.loc[1, 1] = 1
df_mid.loc[N//2-1, N//2-1] = 1
df_high.loc[N-1, N-1] = 1
然后,我在循环中迭代了函数和数据帧(打印只是为了为 SO 制作表格标记):
for name, func in funcs.items():
print(f'| {name} ', end='')
for df in dfs.values():
time = timeit.timeit(setup='import pandas as pd, numpy as np', stmt='res = func(df)',number=1000,globals=locals())
print(f'| {time:.3f} ', end='')
print('|')
结果如下:
方法 | 零 | 低 | 中 | 高 |
---|---|---|---|---|
特德莱尼 | 0.846 | 0.840 | 0.830 | 0.854 |
悟空 1 | 0.331 | 0.321 | 0.316 | 0.313 |
悟空2 | 0.322 | 0.299 | 0.309 | 0.326 |
凯文41 | 0.139 | 0.140 | 0.145 | 0.138 |
其他 1 | 0.800 | 0.780 | 0.784 | 0.790 |
其他 2 | 0.821 | 0.818 | 0.816 | 0.842 |
其他 3 | 0.325 | 0.315 | 0.312 | 0.314 |
可以看出,kevin41 发布的答案是 - 对于这个样本数据 - 是下一个最佳解决方案的两倍多。在那之后,悟空的解决方案和“其他 3 个”解决方案彼此大致相等,最后三个解决方案比它们慢约 2.5 倍。
有趣的是,每种方法的时间和时间是一致的,这表明没有发生短路。df_low
df_high
评论
1赞
Goku - stands with Palestine
11/16/2023
谢谢@Nick感谢您的努力:)
0赞
Nikolaj Š.
11/17/2023
考虑到期望,看到这样做很糟糕是相当令人惊讶的.any()
1赞
Nick
11/18/2023
@NikolajŠ。同意,我本来希望能特别好地处理这个案子。any
low
评论
!=
==