在数据框中查找每月重复值 (pandas)

Finding monthly repeating values in dataframe (pandas)

所以我有一个数据集,其中包含与这些日期相对应的日期和值。

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

也不考虑一个月内重复的值,或者只重复几个月但不是全部的值。

类别通常会与值配对(如示例所示),但有时不会。所以我试着按类别来做,但它没有给我确切的结果。

我目前的方法是过滤重复项,然后获取重复项,出现 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)])]

如有任何帮助,我们将不胜感激。

这是一种旋转和检查 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

首先得到重复的

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

然后删除仅在一个月内重复的那些,即

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

您还可以删除结果 table 中的重复项,即

df_dups = df_dups.groupby(['value', 'category']).apply(lambda g: g.drop_duplicates('date', keep='last))

我将首先按值分组并删除日期重复项:

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]

它既简单又快速...