Панды уникальные значения нескольких столбцов

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'

13 ответов

Решение

pd.unique возвращает уникальные значения из входного массива или столбца или индекса DataFrame.

Входные данные для этой функции должны быть одномерными, поэтому необходимо объединить несколько столбцов. Самый простой способ - выбрать нужные столбцы, а затем просмотреть значения в плоском массиве NumPy. Вся операция выглядит так:

>>> pd.unique(df[['Col1', 'Col2']].values.ravel('K'))
array(['Bob', 'Joe', 'Bill', 'Mary', 'Steve'], dtype=object)

Обратите внимание, что ravel() является методом массива, который возвращает представление (если возможно) многомерного массива. Аргумент 'K' говорит методу, чтобы сгладить массив в порядке, в котором элементы хранятся в памяти (pandas обычно хранит базовые массивы в смежном с Фортраном порядке; столбцы перед строками). Это может быть значительно больше, чем при использовании метода "C" по умолчанию.


Альтернативный способ - выбрать столбцы и передать их np.unique:

>>> np.unique(df[['Col1', 'Col2']].values)
array(['Bill', 'Bob', 'Joe', 'Mary', 'Steve'], dtype=object)

Там нет необходимости использовать ravel() здесь, как метод обрабатывает многомерные массивы. Тем не менее, это, вероятно, будет медленнее, чем pd.unique поскольку он использует алгоритм на основе сортировки, а не хеш-таблицу для определения уникальных значений.

Разница в скорости значительна для больших DataFrames (особенно если есть только несколько уникальных значений):

>>> 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

Я настроил 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)
In [5]: set(df.Col1).union(set(df.Col2))
Out[5]: {'Bill', 'Bob', 'Joe', 'Mary', 'Steve'}

Или же:

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

Обновленное решение, использующее numpy v1.13 +, требует указания оси в np.unique, если используется несколько столбцов, в противном случае массив неявно выравнивается.

import numpy as np

np.unique(df[['col1', 'col2']], axis=0)

Это изменение было введено в ноябре 2016 года: https://github.com/numpy/numpy/commit/1f764dbff7c496d6636dc0430f083ada9ff4e4be

Для тех из нас, кто любит все, что касается панд, применяются и, конечно, лямбда-функции:

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

Вот еще один способ


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

Не -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'])

Вы можете использоватьstackобъединить несколько столбцов иdrop_duplicatesчтобы найти уникальные значения:

      df[['Col1', 'Col2']].stack().drop_duplicates().tolist()

Выход:

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

Если ваш вопрос заключается в том, как получить уникальные значения каждого столбца по отдельности?

Сортировка меток столбцов в списке

      column_labels = ['Col1', 'Col2']

Создать пустой dict

      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)

Получите список уникальных значений по списку имен столбцов:

      cols = ['col1','col2','col3','col4']
unique_l = pd.concat([df[col] for col in cols]).unique()
list(set(df[['Col1', 'Col2']].as_matrix().reshape((1,-1)).tolist()[0]))

Результатом будет ['Мэри', 'Джо', 'Стив', 'Боб', 'Билл']

np.unique(df.values.flatten())
      import pandas as pd
df= pd.DataFrame({'col1':["a","a","b","c","c","d"],'col2': 
                ["x","x","y","y","z","w"],'col3':[1,2,2,3,4,2]})
df

выход

        col1 col2 col3
0   a   x   1
1   a   x   2
2   b   y   2
3   c   y   3
4   c   z   4
5   d   w   2

чтобы получить уникальные значения из всех столбцов

          a={}
    for i in range(df.shape[1]) :
        j=df.columns[i]
        a[j] = df.iloc[:,i].unique()

   for p,q in a.items():
       print( f"unique value in {p} are {list(q)} ")

выход

          unique value in col1 are ['a', 'b', 'c', 'd'] 
    unique value in col2 are ['x', 'y', 'z', 'w'] 
    unique value in col3 are [1, 2, 3, 4] 
Другие вопросы по тегам