在数据框中查找每月重复值 (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]
它既简单又快速...
所以我有一个数据集,其中包含与这些日期相对应的日期和值。
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]
它既简单又快速...