检查数据框列中的所有值是不是相同
Posted
技术标签:
【中文标题】检查数据框列中的所有值是不是相同【英文标题】:Check if all values in dataframe column are the same检查数据框列中的所有值是否相同 【发布时间】:2019-06-21 16:11:38 【问题描述】:我想快速简单地检查 counts
的所有列值是否在数据框中都相同:
在:
import pandas as pd
d = 'names': ['Jim', 'Ted', 'Mal', 'Ted'], 'counts': [3, 4, 3, 3]
pd.DataFrame(data=d)
输出:
names counts
0 Jim 3
1 Ted 4
2 Mal 3
3 Ted 3
我只想要一个简单的条件,即if all counts = same value
然后是print('True')
。
有没有快速的方法来做到这一点?
【问题讨论】:
if len(df['counts'].unique()) ==1: print(True)
怎么样
df.counts.nunique() == 1
?
相关:Check if all elements in a list are identical
df.counts.drop_duplicates().shape[0] ==1
【参考方案1】:
一种有效的方法是将第一个值与其余值进行比较,并使用all
:
def is_unique(s):
a = s.to_numpy() # s.values (pandas<0.24)
return (a[0] == a).all()
is_unique(df['counts'])
# False
虽然最直观的想法可能是计算unique
值的数量并检查是否只有一个,但这对于我们正在尝试做的事情来说会产生不必要的高复杂性。 Numpy 的 np.unique
,由 pandas 的 nunique
调用,实现了底层数组的排序,其使用 quicksort(默认)具有 O(n·log(n))
的估计复杂度。上面的做法是O(n)
。
当我们将其应用于整个数据帧时,性能差异变得更加明显(见下文)。
对于整个数据框
如果想对整个数据帧执行相同的任务,我们可以通过在all
中设置axis=0
来扩展上述内容:
def unique_cols(df):
a = df.to_numpy() # df.values (pandas<0.24)
return (a[0] == a).all(0)
对于共享示例,我们会得到:
unique_cols(df)
# array([False, False])
这是上述方法与其他一些方法(例如使用nunique
(对于pd.Series
)的比较)的基准:
s_num = pd.Series(np.random.randint(0, 1_000, 1_100_000))
perfplot.show(
setup=lambda n: s_num.iloc[:int(n)],
kernels=[
lambda s: s.nunique() == 1,
lambda s: is_unique(s)
],
labels=['nunique', 'first_vs_rest'],
n_range=[2**k for k in range(0, 20)],
xlabel='N'
)
以下是 pd.DataFrame
的时间安排。让我们也与numba
方法进行比较,这在这里特别有用,因为我们可以在给定列中看到重复值时立即利用捷径(注意:numba 方法仅适用于数字数据):
from numba import njit
@njit
def unique_cols_nb(a):
n_cols = a.shape[1]
out = np.zeros(n_cols, dtype=np.int32)
for i in range(n_cols):
init = a[0, i]
for j in a[1:, i]:
if j != init:
break
else:
out[i] = 1
return out
如果我们比较这三种方法:
df = pd.DataFrame(np.concatenate([np.random.randint(0, 1_000, (500_000, 200)),
np.zeros((500_000, 10))], axis=1))
perfplot.show(
setup=lambda n: df.iloc[:int(n),:],
kernels=[
lambda df: (df.nunique(0) == 1).values,
lambda df: unique_cols_nb(df.values).astype(bool),
lambda df: unique_cols(df)
],
labels=['nunique', 'unique_cols_nb', 'unique_cols'],
n_range=[2**k for k in range(0, 20)],
xlabel='N'
)
【讨论】:
我们可以检查是否没有。列中唯一值的个数为 1。 查找唯一值具有不必要的高复杂性来检查这一点。它包含在性能图中以明确@AnupamKumar 你说得对,我完全忘记了性能。【参考方案2】:使用np.unique
更新
len(np.unique(df.counts))==1
False
或者
len(set(df.counts.tolist()))==1
或者
df.counts.eq(df.counts.iloc[0]).all()
False
或者
df.counts.std()==0
False
【讨论】:
这个:df.counts.is_unique - 对我不起作用,但 df.counts.nunique() == 1 有效。我在 Windows 上运行 python 2.7。 @MEdwin 我的意思是你的熊猫版本。 我的熊猫版本是:0.23.4 @MEdwin 检查链接pandas.pydata.org/pandas-docs/stable/reference/api/…,如果仍然返回错误,请在github中提交错误 错误答案:is_unique
检查列中的值是否唯一,即没有重复。所要求的是检查列中的所有值是否相同,这是完全不同的。【参考方案3】:
我认为nunique
做了很多不必要的工作。迭代可以在第一个差异处停止。这个简单通用的解决方案使用itertools
:
import itertools
def all_equal(iterable):
"Returns True if all elements are equal to each other"
g = itertools.groupby(iterable)
return next(g, True) and not next(g, False)
all_equal(df.counts)
甚至可以使用它一次性找到具有恒定内容的所有列:
constant_columns = df.columns[df.apply(all_equal)]
一个更易读但性能较差的替代方案:
df.counts.min() == df.counts.max()
如有必要,请在此处添加skipna=False
。
【讨论】:
【参考方案4】:我更喜欢:
df['counts'].eq(df['counts'].iloc[0]).all()
我发现它最容易阅读,并且适用于所有值类型。根据我的经验,我也发现它足够快。
【讨论】:
很高兴解释为什么这种方法比另一种方法更可取。 添加说明。 警告:如果 df['counts'] 全部为 None,这将返回 False。以上是关于检查数据框列中的所有值是不是相同的主要内容,如果未能解决你的问题,请参考以下文章