k=1 的最近邻距离(以时间为单位)
Nearest neighbor distance for k=1 in units of time
我有以下数据框
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
这基于 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
您可以使用以下代码将日期转换为纪元:
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) 才能将其转换为天数。
您已经在每个键中按日期排序。
因此,您所需要的只是计算同一个键中下一个和上一个日期的距离。
我试过这个(在 Swift 中)来计算格式为 2015-05-22
的 2 个日期之间的距离
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"))
您现在可以遍历一个键中的值来计算给定键的最小距离(当然除了它本身)
您好,这是一个仅使用 Pandas
的可能解决方案
让我们给当前索引起个名字(为了方便,并确保我们能很好地恢复一切)
df['Date'] = df['Date'].astype('datetime64[ns]')
df.index.name = 'id'
我们首先要按日期排序并对每个组应用一个函数,
重要的是要注意,我们将依赖 pandas 保留组内的行顺序这一事实(参见文档)
sorted_df = sorted_df = df.sort_values('Date')
result_df = sorted_df.groupby('A_key').apply(nearest_date_distance)
所以现在让我们看看 nearest_date_distance
函数中有什么
该函数依赖于日期将被排序这一事实,因此我们计算到日期之前的时间和之后日期的时间,当天和第二天之间的差异是负数,这就是我们添加 [=16 的原因=]。最后我们取这两个距离之间的最小值(顺便说一下,最小运算符不会取 time_to_before 的第一行和之后的最后一行时间的缺失值 (NaT))
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
最后我撒了个谎 result_df
将是这种形式的 MultiIndex Serie(不是数据帧):
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
我们可以轻松地将其转换为 DataFrame,并且为我们的原始索引正确命名有助于查看所有内容都与原始 df 中的索引相同。
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
如果您需要结果 Dataframe 上的日期 result_df['Date'] = df['Date']
应该可以解决问题:)
我有以下数据框
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
这基于 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
您可以使用以下代码将日期转换为纪元:
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) 才能将其转换为天数。
您已经在每个键中按日期排序。 因此,您所需要的只是计算同一个键中下一个和上一个日期的距离。 我试过这个(在 Swift 中)来计算格式为 2015-05-22
的 2 个日期之间的距离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"))
您现在可以遍历一个键中的值来计算给定键的最小距离(当然除了它本身)
您好,这是一个仅使用 Pandas
的可能解决方案让我们给当前索引起个名字(为了方便,并确保我们能很好地恢复一切)
df['Date'] = df['Date'].astype('datetime64[ns]')
df.index.name = 'id'
我们首先要按日期排序并对每个组应用一个函数, 重要的是要注意,我们将依赖 pandas 保留组内的行顺序这一事实(参见文档)
sorted_df = sorted_df = df.sort_values('Date')
result_df = sorted_df.groupby('A_key').apply(nearest_date_distance)
所以现在让我们看看 nearest_date_distance
函数中有什么
该函数依赖于日期将被排序这一事实,因此我们计算到日期之前的时间和之后日期的时间,当天和第二天之间的差异是负数,这就是我们添加 [=16 的原因=]。最后我们取这两个距离之间的最小值(顺便说一下,最小运算符不会取 time_to_before 的第一行和之后的最后一行时间的缺失值 (NaT))
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
最后我撒了个谎 result_df
将是这种形式的 MultiIndex Serie(不是数据帧):
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
我们可以轻松地将其转换为 DataFrame,并且为我们的原始索引正确命名有助于查看所有内容都与原始 df 中的索引相同。
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
如果您需要结果 Dataframe 上的日期 result_df['Date'] = df['Date']
应该可以解决问题:)