python - 熊猫:按日期接近过滤
问题描述
我有一个像这样的框架:
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
与第一个相同title
且date
在 70 天内的组。我需要一个按ifid
分组的 s字典,它们之间的距离在 70 天内。这里的预期结果是:title
date
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
.
解决方案
我认为对数据框进行排序可以帮助您更有效地解决问题。
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)
尽管代码变得有点长,但只有两个循环(除了最后一个更改list
into的dict
循环)并且它总共循环n_rows
时间,这意味着它只查看每一行一次。
使用counter
is to use df.iloc
which 使用位置索引(而不是标签或条件语句,如df.loc
),因此计算速度更快 - 使用 O(1)。