我有以下数据框
A_key Date
A1 2016-05-03
A1 2016-09-25
A2 2015-02-25
A2 2015-02-25
A3 2015-10-04
A3 2016-03-15
A3 2016-04-10
A4 2015-09-26
A4 2015-09-26
对于n_neighbor(k)= 1,我想以天为单位获取每个不同的A_key的最近邻居距离,以使输出如下所示
A_key Date Distance
A1 2016-05-03 145
A1 2016-09-25 145
A2 2015-02-25 0
A2 2015-02-25 0
A3 2015-10-04 163
A3 2016-03-15 26
A3 2016-04-10 26
A4 2015-09-26 0
A4 2015-09-26 0
答案 0 :(得分:3)
此操作基于groupby
,将原始df拆分为小的唯一关键数据帧,然后我们使用numpy
广播来加快整个计算速度
df.Date=pd.to_datetime(df.Date)
l=[]
for _, x in df.groupby('A_key'):
s=np.abs((x['Date'].values - x['Date'].values[:,None])).astype('timedelta64[D]').astype(int)
s[[np.arange(len(s))] * 2]=9999
l.append(np.min(s,1))
df['New']=np.concatenate(l)
df
Out[501]:
A_key Date New
0 A1 2016-05-03 145
1 A1 2016-09-25 145
2 A2 2015-02-25 0
3 A2 2015-02-25 0
4 A3 2015-10-04 163
5 A3 2016-03-15 26
6 A3 2016-04-10 26
7 A4 2015-09-26 0
8 A4 2015-09-26 0
答案 1 :(得分:0)
您可以使用以下代码将日期转换为大纪元:
import time
date_time = '2016-05-03 00:00:00'
pattern = '%Y-%m-`enter code here`%d %H:%M:%S'
epoch = int(time.mktime(time.strptime(date_time, pattern)))
然后,只需从其邻居值中减去该值即可。请注意,结果将以毫秒为单位,因此您必须除以(1000 * 60 * 60 * 24)才能将其转换为天数。
答案 2 :(得分:0)
您已经在每个键中按日期排序。 因此,您所需要做的就是计算同一键中到下一个和上一个日期的距离。 我试过了(在Swift中)计算2个日期之间的距离,格式为2015-05-22
func dist(_ d1: String, _ d2: String) -> Int {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "YYYY-MM-DD"
if let date1 = dateFormatter.date(from: d1), let date2 = dateFormatter.date(from: d2) {
let distance = date1.timeIntervalSince(date2) / 86400
return abs(Int(distance))
} else { return 0 }
}
print(dist("2015-05-25", "2015-05-22"))
现在,您可以循环浏览一个键中的值,以计算给定键的最小距离(当然,它本身除外)
答案 3 :(得分:0)
您好,这里是仅使用熊猫的可能解决方案
让我们给当前索引起一个名字(为了方便起见,请确保我们能很好地恢复所有内容)
df['Date'] = df['Date'].astype('datetime64[ns]')
df.index.name = 'id'
我们首先要按日期排序,然后对每个组应用一个函数, 重要的是要注意,我们将依靠大熊猫在组内保留行顺序这一事实(请参见文档)
sorted_df = sorted_df = df.sort_values('Date')
result_df = sorted_df.groupby('A_key').apply(nearest_date_distance)
现在让我们看看nearest_date_distance
函数内部有什么
该函数依赖于Date将被排序的事实,因此我们计算到前一个日期的时间和到后一个日期的时间,当前天与第二天之间的差为负,这就是为什么我们添加{{1 }}。最后,我们采用这两个距离之间的最小值(顺便说一句,min运算符不会采用您在time_to_before的第一行和time toto的最后一行的缺失值(NaT))
.abs()
最后我撒谎了一点,def nearest_date_distance(sub):
time_to_before = sub['Date'].diff()
time_to_after = sub['Date'].diff(-1).abs()
nearest_date_distance = pd.concat([time_to_before, time_to_after],axis=1).min(axis=1)
nearest_date_distance.name = 'Distance'
return nearest_date_distance
将是这种形式的MultiIndex Serie(不是数据框):
result_df
我们可以轻松地将其转换为DataFrame,并为原始索引进行适当的命名有助于确保所有索引都与原始df中的索引相同。
A_key id
A1 0 145 days
1 145 days
A2 2 0 days
3 0 days
A3 4 163 days
5 26 days
6 26 days
A4 7 0 days
8 0 days
,如果您需要在生成的数据框result_df =sorted_df.groupby('A_key').apply(nearest_date_distance).reset_index(level=0)
A_key Distance
id
0 A1 145 days
1 A1 145 days
2 A2 0 days
3 A2 0 days
4 A3 163 days
5 A3 26 days
6 A3 26 days
7 A4 0 days
8 A4 0 days
上使用日期,就可以做到这一点:)