首页 > 解决方案 > 熊猫:按日期接近过滤

问题描述

我有一个像这样的框架:

     id         title       date
0  1211  jingle bells 2019-01-15
1  1212  jingle bells 2019-01-15
2  1225      tom boat 2019-06-15
3  2112      tom boat 2019-06-15
4  3122      tom boat 2017-03-15
5  1762      tom boat 2017-03-15

Anitem被定义为id与第一个相同titledate在 70 天内的组。我需要一个按ifid分组的 s字典,它们之间的距离在 70 天内。这里的预期结果是:titledate

d = {0: [1211,1212], 1: [1225,2112], 2: [3122,1762]}

任何给定title的字典条目都可以有不限数量或只有一个。id对一个标题是唯一的。目前,我做了类似的事情:

itemlist = []
for i in list(df.title):
    dates = list(df.loc[df.title==i,'date'])
    if (max(dates)-min(dates)).days > 70:
        items = []
        while len(dates)>0:
            extract = [i for i in dates if (i-min(dates)).days<70]
            items.append(list(df.loc[(df.title==i)&(df.date.isin(extract)),'id'])
            dates = [i for i in dates if i not in extract
    else:
        items = [list(df.loc[df.title==i,'id'])]
    itemlist += items
d = {j:i for i in range(len(itemlist)) for j in itemlist[i]}

它还没有完全工作,我正在修复错误。也就是说,我觉得这是很多迭代 - 关于如何更好地做到这一点的任何想法?另一个可接受的输出是数据帧列表,每个item.

标签: pythonpandasdataframe

解决方案


我认为对数据框进行排序可以帮助您更有效地解决问题。

df = df.sort_values(['title', 'date'])

itemlist = []
counter = 0 # to get items at constant time

for title in set(df.title):
    dates = df.loc[df['title']==title].date.tolist()
    item = []
    min_date = dates[0]
    for date in dates:
        if (date-min_date).days>70: # we need a new item
            itemlist.append(item) # append original item
            item = [df.iloc[counter, 0]] # new item
            min_date = date
        else:
            item.append(df.iloc[counter, 0])
        counter += 1
    itemlist.append(item)

d = {i:j for i,j in enumerate(itemlist)}

print(d)

尽管代码变得有点长,但只有两个循环(除了最后一个更改listinto的dict循环)并且它总共循环n_rows时间,这意味着它只查看每一行一次。
使用counteris to use df.ilocwhich 使用位置索引(而不是标签或条件语句,如df.loc),因此计算速度更快 - 使用 O(1)。


推荐阅读