pandas 生成显示连续日期之间的非重复值数的列

y0u0uwnf  于 2023-04-04  发布在  其他
关注(0)|答案(3)|浏览(85)

我有一个pandas dataframe,格式如下:
| 用户ID|日期|帐簿ID|
| --------------|--------------|--------------|
| 1|2022年7月15日|10个|
| 1|2022年7月16日|十一|
| 1|2022年7月16日|十二岁|
| 1|2022年7月17日|十二岁|
从这个表中,我想得到的是每个用户连续每天的新BookId的数量。例如,根据上表,用户在2022-07-16阅读了两本新书,而在2022-07-17没有阅读新书,因为他/她在前一天已经阅读了一本新书。这是预期的结果:
| 用户ID|2022年7月16日|2022年7月17日|
| --------------|--------------|--------------|
| 1|第二章|0|
我觉得这个任务可以通过按UserId和Date对数据进行分组,然后使用apply lambda函数来完成。然而,我无法管理它。我最终得到了以下代码,它使用了for循环。有没有一种方法可以在没有循环的情况下用更短的代码实现这一点?

df = studentAnswers.groupby('StudentId')
df.apply(findObjDiff)

def findObjDiff(df):
    print(df.StudentId.head(3))
    dataDict = {}
    dates = list(df.Date)
    dates.sort()
    for d in dates:
        ixNext = dates.index(d) + 1
        if(ixNext > len(dates)):
            break
        dateNext = dates[ixNext]
        objListPrev = set(df[df.Date == d].ObjectiveId)
        objListNext = set(df[df.Date == dateNext].ObjectiveId)
        dataDict[df.StudentId] = {dateNext : {'Different': len(objListPrev - objListNext)}}

    return dataDict
b5buobof

b5buobof1#

使用duplicatedpivot_table

(df.assign(count=~df['BookId'].duplicated())
   .pivot_table(index='UserId', columns='Date', values='count', aggfunc='sum')
   .astype(int).reset_index().rename_axis(columns=None)
)

仅考虑重复的连续天数:

s = df.groupby(pd.to_datetime(df['Date']))['BookId'].agg(set)

(df.assign(count=(s-s.shift(1, freq='D')).str.len().to_numpy())
   .pivot_table(index='UserId', columns='Date', values='count', aggfunc='sum')
   .astype(int).reset_index().rename_axis(columns=None)
)

输出:

UserId  2022-07-15  2022-07-16  2022-07-17
0       1           1           2           0
xqnpmsa8

xqnpmsa82#

下面是一个解决方案:

(df.loc[df.sort_values('Date')
.groupby(['UserId','BookId'])['Date'].transform(lambda x: x.diff().dt.days.ne(1))]
.groupby(['UserId','Date'])['BookId'].nunique()
.reindex(pd.MultiIndex.from_product([df['UserId'].unique(),df['Date'].unique()],names = ['User',None]),fill_value=0)
.unstack())

输出:

2022-07-15  2022-07-16  2022-07-17
User                                    
1              1           2           0
d4so4syb

d4so4syb3#

import pandas as pd

df = pd.DataFrame({'UserId': [1, 1, 1, 1],
                   'Date': ['2022-07-15', '2022-07-16', '2022-07-16', '2022-07-17'],
                   'BookId': [10, 11, 12, 12],
                   })

r = (df.drop_duplicates(subset='BookId')
       .pivot_table(index='UserId', columns='Date', values='BookId', aggfunc='count')
       .reset_index()
       .rename_axis(columns=''))

m = ~df['Date'].isin(r.columns)

for dat in df[m]['Date']:
    r[dat] = 0

print(r)

结果

UserId  2022-07-15  2022-07-16  2022-07-17
0       1           1           2           0

相关问题