Удалить низкочастотные значения из pandas.dataframe

Как я могу удалить значения из столбца в pandas.DataFrame, что происходит редко, т.е. с низкой частотой? Пример:

In [4]: df[col_1].value_counts()

Out[4]: 0       189096
        1       110500
        2        77218
        3        61372
              ...
        2065         1
        2067         1
        1569         1
        dtype: int64

Итак, мой вопрос: как удалить такие значения, как 2065, 2067, 1569 и другие? И как я могу сделать это для всех столбцов, которые содержат .value_counts() как это?

ОБНОВЛЕНИЕ: О "низком" я имею в виду такие значения, как 2065, Это значение встречается в col_1 1 (один) раз, и я хочу удалить такие значения, как это.

3 ответа

Решение

Я вижу, что есть два способа сделать это.

Для всего DataFrame

Этот метод удаляет значения, которые встречаются нечасто во всем DataFrame. Мы можем сделать это без циклов, используя встроенные функции, чтобы ускорить процесс.

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randint(0, high=9, size=(100,2)),
         columns = ['A', 'B'])

threshold = 10 # Anything that occurs less than this will be removed.
value_counts = df.stack().value_counts() # Entire DataFrame 
to_remove = value_counts[value_counts <= threshold].index
df.replace(to_remove, np.nan, inplace=True)

Колонка-на-колонки

Этот метод удаляет записи, которые встречаются нечасто в каждом столбце.

import pandas as np
import numpy as np

df = pd.DataFrame(np.random.randint(0, high=9, size=(100,2)),
         columns = ['A', 'B'])

threshold = 10 # Anything that occurs less than this will be removed.
for col in df.columns:
    value_counts = df[col].value_counts() # Specific column 
    to_remove = value_counts[value_counts <= threshold].index
    df[col].replace(to_remove, np.nan, inplace=True)

Вы, вероятно, не хотите удалять всю строку в вашем DataFrame, если только один столбец имеет значения ниже вашего порога, поэтому я просто удалил эти точки данных и заменил их на None,

Я перебираю каждый столбец и выполняю value_counts на каждой. Затем я получаю значения индекса для каждого элемента, который находится на уровне или ниже целевого порогового значения. Наконец, я использую .loc чтобы найти значения этих элементов в столбце, а затем заменить их None,

df = pd.DataFrame({'A': ['a', 'b', 'b', 'c', 'c'], 
                   'B': ['a', 'a', 'b', 'c', 'c'], 
                   'C': ['a', 'a', 'b', 'b', 'c']})

>>> df
   A  B  C
0  a  a  a
1  b  a  a
2  b  b  b
3  c  c  b
4  c  c  c

threshold = 1  # Remove items less than or equal to threshold
for col in df:
    vc = df[col].value_counts()
    vals_to_remove = vc[vc <= threshold].index.values
    df[col].loc[df[col].isin(vals_to_remove)] = None

>>> df
      A     B     C
0  None     a     a
1     b     a     a
2     b  None     b
3     c     c     b
4     c     c  None

Сapplyэто можно сделать одной строкой.value_countsвозвращает количество уникальных значений. Вхождения сопоставляются с каждым значением с помощьюmap.whereзаменяет все значения, где условие не выполняется ( здесь : количество вхождений больше 1) на NaN .

      In [6]: df = pd.DataFrame({'A': ['a', 'b', 'b', 'c', 'c'], 'B': ['a', 'a', 'b', 'c', 'c'],  'C': ['a', 'a', 'b', 'b', 'c']})

In [7]: df
Out[7]: 
   A  B  C
0  a  a  a
1  b  a  a
2  b  b  b
3  c  c  b
4  c  c  c

In [8]: df.apply(lambda col: col.where(col.map(col.value_counts()) > 1))
Out[8]: 
     A    B    C
0  NaN    a    a
1    b    a    a
2    b  NaN    b
3    c    c    b
4    c    c  NaN

Кредиты @Alexander за набор данных.

Другие вопросы по тегам