pandas多列唯一值

210
df = pd.DataFrame({'Col1': ['Bob', 'Joe', 'Bill', 'Mary', 'Joe'],
                   'Col2': ['Joe', 'Steve', 'Bob', 'Bob', 'Steve'],
                   'Col3': np.random.random(5)})

什么是返回'Col1'和'Col2'的唯一值的最佳方法?

期望输出为

'Bob', 'Joe', 'Bill', 'Mary', 'Steve'

8
参见在pandas数据帧中选择列的唯一值组合并计数相关问题。那里的选定答案使用了df1.groupby(['A','B']).size().reset_index().rename(columns={0:'count'}) - Paul Rougieux
12个回答

289

pd.unique函数用于从输入数组或DataFrame列或索引中返回唯一值。

此函数的输入必须是一维的,因此需要合并多个列。最简单的方法是选择所需的列,然后在展平的NumPy数组中查看值。 整个操作看起来像这样:

>>> pd.unique(df[['Col1', 'Col2']].values.ravel('K'))
array(['Bob', 'Joe', 'Bill', 'Mary', 'Steve'], dtype=object)
注意ravel()是一个数组方法,如果可能的话返回一个多维数组的视图。参数'K'告诉方法按照存储在内存中的元素顺序来展开数组(Pandas通常以Fortran连续顺序存储底层数组;列在行之前)。相比使用该方法的默认 'C' 顺序,这样做可以显著提高速度。


另一种方法是选择列并将它们传递给np.unique
>>> np.unique(df[['Col1', 'Col2']].values)
array(['Bill', 'Bob', 'Joe', 'Mary', 'Steve'], dtype=object)

在这里没有必要使用ravel()方法,因为该方法可以处理多维数组。即使如此,这种方法比pd.unique方法更慢,因为它使用基于排序的算法而不是哈希表来确定唯一值。

对于较大的数据框(特别是如果只有少数唯一值),速度差异显著:

>>> df1 = pd.concat([df]*100000, ignore_index=True) # DataFrame with 500000 rows
>>> %timeit np.unique(df1[['Col1', 'Col2']].values)
1 loop, best of 3: 1.12 s per loop

>>> %timeit pd.unique(df1[['Col1', 'Col2']].values.ravel('K'))
10 loops, best of 3: 38.9 ms per loop

>>> %timeit pd.unique(df1[['Col1', 'Col2']].values.ravel()) # ravel using C order
10 loops, best of 3: 49.9 ms per loop

5
如何获得一个数据框(dataframe)而不是一个数组(array)? - Lisle
1
@Lisle:两种方法都返回NumPy数组,因此您必须手动构造它,例如 pd.DataFrame(unique_values)。没有直接获取DataFrame的好方法。 - Alex Riley
@Lisle,由于他使用了pd.unique,因此它返回一个numpy.ndarray作为最终输出。这是你想问的吗? - Ash Upadhyay
6
@Lisle,也许这个命令是想删除数据框df中'C1'、'C2'和'C3'这三列中的重复行。命令为:df = df.drop_duplicates(subset=['C1','C2','C3'])。 - tickly potato
2
为了将你所需要的列仅保留到一个数据帧中,你可以执行 df.groupby(['C1', 'C2', 'C3']).size().reset_index().drop(columns=0)。这将会按照默认方式进行分组,并选取唯一组合,计算每个组内项目数量。reset_index 将把多级索引变成平坦的二维表格。最后一步就是移除项目数量列。 - andrnev

15
我已经创建了一个DataFrame,并在其列中放置了一些简单的字符串。
>>> df
   a  b
0  a  g
1  b  h
2  d  a
3  e  e

你可以将你感兴趣的列连接起来,并调用unique函数:
>>> pandas.concat([df['a'], df['b']]).unique()
array(['a', 'b', 'd', 'e', 'g', 'h'], dtype=object)

1
当你有类似这样的东西时,这是不起作用的 this_is_uniuqe = { 'col1': ["Hippo", "H"], "col2": ["potamus", "ippopotamus"], } - sixtyfootersdude

11
In [5]: set(df.Col1).union(set(df.Col2))
Out[5]: {'Bill', 'Bob', 'Joe', 'Mary', 'Steve'}

或者:

set(df.Col1) | set(df.Col2)

9

4

对于我们这些喜欢熊猫、应用和lambda函数的人:

df['Col3'] = df[['Col1', 'Col2']].apply(lambda x: ''.join(x), axis=1)

3

以下是另一种方法


import numpy as np
set(np.concatenate(df.values))

2

pandas解决方案:使用set()。

import pandas as pd
import numpy as np

df = pd.DataFrame({'Col1' : ['Bob', 'Joe', 'Bill', 'Mary', 'Joe'],
              'Col2' : ['Joe', 'Steve', 'Bob', 'Bob', 'Steve'],
               'Col3' : np.random.random(5)})

print df

print set(df.Col1.append(df.Col2).values)

输出:

   Col1   Col2      Col3
0   Bob    Joe  0.201079
1   Joe  Steve  0.703279
2  Bill    Bob  0.722724
3  Mary    Bob  0.093912
4   Joe  Steve  0.766027
set(['Steve', 'Bob', 'Bill', 'Joe', 'Mary'])

1
df = pd.DataFrame({'Col1': ['Bob', 'Joe', 'Bill', 'Mary', 'Joe'],
               'Col2': ['Joe', 'Steve', 'Bob', 'Bob', 'Steve'],
               'Col3': np.random.random(5)})

如果你的问题是如何单独获取每列的唯一值?
将列标签排序为列表。
column_labels = ['Col1', 'Col2']

创建一个空字典。
unique_dict = {}

遍历选定的列,获取它们的唯一值

for column_label in column_labels: 
    unique_values = df[column_label].unique()
    unique_dict.update({column_label: unique_values})
unique_ser = pd.Series(unique_dict)
print(unique_ser)

0
获取一列列名的列表中独特的值:
cols = ['col1','col2','col3','col4']
unique_l = pd.concat([df[col] for col in cols]).unique()

0
list(set(df[['Col1', 'Col2']].as_matrix().reshape((1,-1)).tolist()[0]))

输出将是 ['Mary','Joe','Steve','Bob','Bill']

DataFrame 对象没有 as_matrix 属性。 - arilwan
根据您使用的版本不同,请参见https://pandas.pydata.org/pandas-docs/version/0.25.1/reference/api/pandas.DataFrame.as_matrix.html。 - smishra

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