以下是我正在查看的数据集。
Input:-
Date Name
01/01/2017 A
01/03/2017 B
02/05/2017 A
03/17/2017 C
04/08/2017 D
05/10/2017 B
06/12/2017 D
Output:-
Date Unique Count
Jan 2017 2
Feb 2017 2
Mar 2017 3
Apr 2017 3
May 2017 3
Jun 2017 2
我希望获得"姓名"在前3个月的滚动基础上。例如,对于日期06/12/2017,前3个月,包括自己是4月,5月,6月。所以四月已经有了#34; D",可能有" B"和六月有" D"。因此,6月份的独特计数为2.同样适用于所有其他月份。
我正在寻找可以帮助我实现这一目标的熊猫功能。或任何可以实现此目的的自定义代码。
感谢任何帮助。
答案 0 :(得分:2)
尝试:
months = pd.to_datetime(d.loc[:, "Date"]).dt.to_period("M")
out = pd.DataFrame([
(month, len(d.loc[(-2 <= months - month) & (months - month <= 0), "Name"].unique()))
for month in months.unique()])
答案 1 :(得分:1)
首先创建DataFrame并将日期设置为索引:
df= pd.DataFrame({'Date': ['01-01-2017', '01-03-2017', '02-05-2017', '03-17-2017', '04-08-2017', '05-10-2017', '06-12-2017'],
'Name': ['A','B', 'A', 'C', 'D', 'B', 'D']})
df['Date'] = pd.to_datetime(df['Date'])
df = df.set_index('Date')
首先,我们按月分组,以便以后我们可以每月进行滚动计数:
groups = df.groupby(pd.TimeGrouper(freq='M'))
现在,我们需要一种方法来保留我们每个月都能看到的所有名字。我们可以将它们列入清单。
all_names_per_month = groups['Name'].apply(list)
这看起来像:
Date
2017-01-31 [A, B]
2017-02-28 [A]
2017-03-31 [C]
2017-04-30 [D]
2017-05-31 [B]
2017-06-30 [D]
Freq: M, Name: Name, dtype: object
接下来,理想情况下,我们希望使用all_names_per_month.rolling(3).apply(...)
,但不幸的是,apply
不能使用非数字值,因此我们可以定义一个自定义滚动功能来获取我们我们想要的价值观:
def get_values(window_len, df):
values = []
for i in range(1, len(df)+1):
if i < window_len:
values.append(len(set(itertools.chain.from_iterable(all_names_per_month.iloc[0: i]))))
else:
values.append(len(set(itertools.chain.from_iterable(all_names_per_month.iloc[i-3:i]))))
return values
values = get_values(3, all_names_per_month)
这给了我们:
[2, 2, 3, 3, 3, 2]
最后,我们可以将这些值放入具有适当索引的DataFrame中,然后我们将其修改为看上面指定的方式:
result = pd.DataFrame(data=values, columns=['Unique Count'], index=all_names_per_month.index)
result.index = result.index.strftime('%B %Y')
result
Unique Count
January 2017 2
February 2017 2
March 2017 3
April 2017 3
May 2017 3
June 2017 2