k = 1的最近邻居距离,单位为时间

时间:2019-01-16 22:02:38

标签: python pandas datediff nearest-neighbor date-difference

我有以下数据框

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

4 个答案:

答案 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 上使用日期,就可以做到这一点:)