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)
Но тогда я не могу понять, как удалить те записи, которые имеют низкое количество...
4 ответов:
Edit: спасибо @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
New в 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функция (первый аргумент фильтра) применяется к каждой группе (подкадру), и результаты включают элементы исходного фрейма данных, принадлежащие группам, которые оцениваются как истинные.
Примечание: в 0.12 порядок отличается от исходного кадра данных , это было исправлено в 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
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Давайте получим, где число > 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
Вот некоторые времена выполнения для нескольких решений, опубликованных здесь, наряду с одним, который не был (используя
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
Comments