Нахождение ежемесячных повторяющихся значений в кадре данных (pandas) - PullRequest
2 голосов
/ 05 марта 2020

Итак, у меня есть набор данных, который включает даты и значения, соответствующие этим датам.

date  value  category
1951-07 199 1
1951-07 130 3
1951-07 50  5
1951-08 199 1
1951-08 50  5
1951-08 199 1
1951-09 184 2
1951-09 50  5
1951-09 13  13

Теперь моя цель - найти значения, которые повторяются каждый месяц. В результате получается такой кадр:

date  value  category
1951-07 50  5
1951-08 50  5
1951-09 50  5

Также не касается значений, которые повторяются в течение месяца или повторяются только в течение нескольких месяцев, но не все.

Категории часто имеют значение pai (как показано в примере), но иногда это не так. Поэтому я попытался сделать это по категориям, но это не дало мне точных результатов.

Мой текущий подход состоит в том, чтобы отфильтровать дубликаты, а затем получить их, которые встречаются 12 раз (так как я ищу в год). Но это также дает мне значения, которые повторяют 12 сторон в течение месяца.

df = df[df.duplicated(['value'],keep=False)]
v = df.value.value_counts()
df_12 = df[df.value.isin(v.index[v.gt(12)])]

Любая помощь будет оценена.

Ответы [ 3 ]

3 голосов
/ 05 марта 2020

Я бы сначала сгруппировал по значениям и удалил дубликаты по датам:

tmp = df.groupby('value')['date'].apply(lambda x: x.drop_duplicates())

Ваш образец даст:

value   
13     8    1951-09
50     2    1951-07
       4    1951-08
       7    1951-09
130    1    1951-07
184    6    1951-09
199    0    1951-07
       3    1951-08
Name: date, dtype: object

Тогда мы сможем безопасно посчитать значения и сохранить только те, которые с ожидаемым количеством ::

total = tmp.groupby(level=0).count()
total = total[total == 3]

Мы получаем:

value
50    3
Name: date, dtype: int64

Мы можем окончательно отфильтровать исходный кадр данных:

df[df['value'].isin(total.index)]

, получив ожидаемое:

      date  value  category
2  1951-07     50         5
4  1951-08     50         5
7  1951-09     50         5

Из комментария Jezrael первыми шагами для сборки total должны стать:

total = df.drop_duplicates(['date', 'value'])[['date', 'value']
                                              ].groupby('value').count()['date']
total = total[total == 3]

это и проще, и быстрее ...

1 голос
/ 05 марта 2020

Сначала получите дубликаты

df_dups = df[df.duplicated(subset=['value', 'category'], keep=False)]

Затем удалите дубликаты внутри одного месяца, т. Е.

df_dups = df_dups.groupby(['value', 'category']).filter(lambda g: g['date'].nunique() > 1)

Вы также можете удалить дубликаты внутри результирующей таблицы, т.е.

df_dups = df_dups.groupby(['value', 'category']).apply(lambda g: g.drop_duplicates('date', keep='last))
1 голос
/ 05 марта 2020

Вот один из способов поворота и проверки, где all строки notna:

piv = df.pivot_table(index='date', columns='category', values='value', aggfunc='first')

df[df.category.eq(piv.notna().all(0).idxmax())]

    date    value  category
2  1951-07     50         5
4  1951-08     50         5
7  1951-09     50         5

Где:

print(piv)

category     1      2      3     5     13
date                                     
1951-07   199.0    NaN  130.0  50.0   NaN
1951-08   199.0    NaN    NaN  50.0   NaN
1951-09     NaN  184.0    NaN  50.0  13.0
...