Python Pandas: удалять записи в зависимости от количества вхождений
Я пытаюсь удалить записи из фрейма данных, которые происходят менее 100 раз.
Кадр данных data
выглядит следующим образом:
pid tag
1 23
1 45
1 62
2 24
2 45
3 34
3 25
3 62
Теперь я подсчитываю количество появлений тегов, подобных этому:
bytag = data.groupby('tag').aggregate(np.count_nonzero)
Но тогда я не могу понять, как удалить те записи, которые имеют низкий счет...
Ответы
Ответ 1
Изменить: Благодаря @WesMcKinney для показа этого гораздо более прямого способа:
data[data.groupby('tag').pid.transform(len) > 1]
import pandas
import numpy as np
data = pandas.DataFrame(
{'pid' : [1,1,1,2,2,3,3,3],
'tag' : [23,45,62,24,45,34,25,62],
})
bytag = data.groupby('tag').aggregate(np.count_nonzero)
tags = bytag[bytag.pid >= 2].index
print(data[data['tag'].isin(tags)])
дает
pid tag
1 1 45
2 1 62
4 2 45
7 3 62
Ответ 2
Новое в 0.12, объекты groupby имеют метод filter
, позволяющий выполнять следующие типы операций:
In [11]: g = data.groupby('tag')
In [12]: g.filter(lambda x: len(x) > 1) # pandas 0.13.1
Out[12]:
pid tag
1 1 45
2 1 62
4 2 45
7 3 62
Функция (первый аргумент фильтра) применяется к каждой группе (подкадр), а результаты включают элементы исходного DataFrame, принадлежащие группам, которые оцениваются как True.
Примечание: в 0.12 порядок отличается от исходного DataFrame, это было исправлено в 0,13 +:
In [21]: g.filter(lambda x: len(x) > 1) # pandas 0.12
Out[21]:
pid tag
1 1 45
4 2 45
2 1 62
7 3 62
Ответ 3
df = pd.DataFrame([(1, 2), (1, 3), (1, 4), (2, 1),(2,2,)], columns=['col1', 'col2'])
In [36]: df
Out[36]:
col1 col2
0 1 2
1 1 3
2 1 4
3 2 1
4 2 2
gp = df.groupby('col1').aggregate(np.count_nonzero)
In [38]: gp
Out[38]:
col2
col1
1 3
2 2
позволяет получить, где count > 2
tf = gp[gp.col2 > 2].reset_index()
df[df.col1 == tf.col1]
Out[41]:
col1 col2
0 1 2
1 1 3
2 1 4
Ответ 4
Ниже приведены некоторые примеры выполнения нескольких решений, размещенных здесь, наряду с тем, который не был (с использованием value_counts()
), который намного быстрее, чем другие решения:
Создайте данные:
import pandas as pd
import numpy as np
# Generate some 'users'
np.random.seed(42)
df = pd.DataFrame({'uid': np.random.randint(0, 500, 500)})
# Prove that some entries are 1
print "{:,} users only occur once in dataset".format(sum(df.uid.value_counts() == 1))
Вывод:
171 users only occur once in dataset
Время несколько разных способов удаления пользователей только с одной записью. Они выполнялись в отдельных ячейках в ноутбуке Jupyter:
%%timeit
df.groupby(by='uid').filter(lambda x: len(x) > 1)
%%timeit
df[df.groupby('uid').uid.transform(len) > 1]
%%timeit
vc = df.uid.value_counts()
df[df.uid.isin(vc.index[vc.values > 1])].uid.value_counts()
Они дали следующие результаты:
10 loops, best of 3: 46.2 ms per loop
10 loops, best of 3: 30.1 ms per loop
1000 loops, best of 3: 1.27 ms per loop