查找Pandas DataFrame中所有列相等的行

49 投票
5 回答
42466 浏览
提问于 2025-04-18 00:15

我有一个数据表,里面有一些字符。我想要一个布尔值(真或假),这个值可以告诉我每一行的所有列是否都有相同的值。

举个例子,我有

df = [  a   b   c   d

0  'C'   'C'   'C'   'C' 

1  'C'   'C'   'A'   'A'

2  'A'   'A'   'A'   'A' ]

我想要的结果是

0  True

1  False

2  True

我试过用 .all 方法,但好像只能检查所有字符是否都等于某一个字母。我想到的另一种方法是对每一行做一次唯一值检查,看看结果是不是1?提前谢谢你。

5 个回答

2
df = pd.DataFrame.from_dict({'a':'C C A'.split(),
                        'b':'C C A'.split(),
                        'c':'C A A'.split(),
                        'd':'C A A'.split()})
df.apply(lambda x: len(set(x)) == 1, axis=1)
0     True
1    False
2     True
dtype: bool

解释:如果这一行的所有元素都一样,set(x) 里就只有一个元素。这里的 axis=1 选项是指对每一行应用指定的函数。

3

你可以使用 nunique(axis=1) 这个方法,这样就能把结果(加到一个新列里)得到:

df['unique'] = df.nunique(axis=1) == 1

@yo-and-ben-w 的回答使用了 eq(1),但我觉得 == 1 更容易理解。

12

nunique: 在0.20.0版本中新增加的功能。(根据Jez的基准测试,如果性能不是很重要,你可以使用这个方法)

df.nunique(axis = 1).eq(1)
Out[308]: 
0     True
1    False
2     True
dtype: bool

或者你可以用map配合set来实现

list(map(lambda x : len(set(x))==1,df.values))
18

通过第一列来比较array,并检查每一行是否都是True

在numpy中使用相同的解决方案,可以获得更好的性能:

a = df.values
b = (a == a[:, [0]]).all(axis=1)
print (b)
[ True  True False]

如果需要Series的话:

s = pd.Series(b, axis=df.index)

比较不同的解决方案:

data = [[10,10,10],[12,12,12],[10,12,10]]
df = pd.DataFrame(data,columns=['Col1','Col2','Col3'])

#[30000 rows x 3 columns]
df = pd.concat([df] * 10000, ignore_index=True)

#jez - numpy array
In [14]: %%timeit
    ...: a = df.values
    ...: b = (a == a[:, [0]]).all(axis=1)
141 µs ± 3.23 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

#jez - Series 
In [15]: %%timeit
    ...: a = df.values
    ...: b = (a == a[:, [0]]).all(axis=1)
    ...: pd.Series(b, index=df.index)
169 µs ± 2.02 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

#Andy Hayden
In [16]: %%timeit
    ...: df.eq(df.iloc[:, 0], axis=0).all(axis=1)
2.22 ms ± 68.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

#Wen1
In [17]: %%timeit
    ...: list(map(lambda x : len(set(x))==1,df.values))
56.8 ms ± 1.04 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

#K.-Michael Aye
In [18]: %%timeit
    ...: df.apply(lambda x: len(set(x)) == 1, axis=1)
686 ms ± 23.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

#Wen2    
In [19]: %%timeit
    ...: df.nunique(1).eq(1)
2.87 s ± 115 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
56

我觉得最简单的方法就是用“eq”来检查所有列和第一列是否相等:

In [11]: df
Out[11]: 
   a  b  c  d
0  C  C  C  C
1  C  C  A  A
2  A  A  A  A

In [12]: df.iloc[:, 0]
Out[12]: 
0    C
1    C
2    A
Name: a, dtype: object

In [13]: df.eq(df.iloc[:, 0], axis=0)
Out[13]: 
      a     b      c      d
0  True  True   True   True
1  True  True  False  False
2  True  True   True   True

现在你可以用“all”来判断(如果它们都和第一个项目相等,那它们就是相等的):

In [14]: df.eq(df.iloc[:, 0], axis=0).all(1)
Out[14]: 
0     True
1    False
2     True
dtype: bool

撰写回答