首页 > 解决方案 > Python - 多个锚点的日期差异

问题描述

我希望通过 ID 之间的某些锚点来查找日期差异。为了详细说明锚点,它们只是我在数据集中感兴趣的日期。一个 ID 可能有一个、两个、三个或更多锚点。

第一个锚点之前的日期应该与第一个锚点相关联。如果只有一个锚点,则所有日期都应与第一个锚点相关联。如果有相同 ID 的第二个锚点,则第一个锚点之后的所有日期都应与第二个锚点日期相关联。如果有第三个锚点,那么第二个锚点之后的所有日期都应该与第三个锚点相关联,依此类推。

输入

ID  Date        Anchor
123 1/5/2018    N
123 4/10/2018   N
123 5/8/2018    Y
123 5/10/2018   N
123 6/14/2018   N
123 7/8/2018    Y
123 8/2/2018    N
123 10/3/2018   N
234 1/4/2018    N
234 2/5/2018    Y 
234 4/10/2018   N
234 5/6/2018    Y

预期输出:

ID  Date        Anchor   Date Diff (Days)
123 1/5/2018    N       -123
123 4/10/2018   N       -28
123 5/8/2018    Y        0
123 5/10/2018   N       -59
123 6/14/2018   N       -24
123 7/8/2018    Y        0
123 8/2/2018    N        25
123 10/3/2018   N        87
234 1/4/2018    N       -32
234 2/5/2018    Y        0
234 4/10/2018   N       -26
234 5/6/2018    Y        0

代码尝试

df['Date'] = pd.to_datetime(df['Date'])
df.groupby('ID')

anchors = dict()
for index, row in df.iterrows():
    if row['Anchor Date'] == 'Y':
        if row['ID'] in anchors:
            anchors[row['ID']].append(row['Date'])
        else:
            anchors[row['ID']] = [row['Date']]

daysDifference = list()
for index, row in df.iterrows():
    if row['Anchor Date'] == 'N':
        delta = 9999 #Arbitrary value
        for anchorDate in anchors[row['ID']]:
            if abs((row['Date'] - anchorDate).days) < delta:
                delta = (row['Date'] - anchorDate).days
        daysDifference.append(delta)
    else:
        daysDifference.append(0)

df['Diff'] = daysDifference

标签: pythonpandas

解决方案


您可以使用wheregroupby.bfill到作业,使用ffill来完成填充。

s = pd.to_datetime(df['Date'])
df['diff_'] = (s - s.where(df['Anchor'].eq('Y'))
                    .groupby(df['ID'])
                    .apply(lambda x: x.bfill().ffill())
              ).dt.days
print (df)
     ID       Date Anchor  diff_
0   123   1/5/2018      N   -123
1   123  4/10/2018      N    -28
2   123   5/8/2018      Y      0
3   123  5/10/2018      N    -59
4   123  6/14/2018      N    -24
5   123   7/8/2018      Y      0
6   123   8/2/2018      N     25
7   123  10/3/2018      N     87
8   234   1/4/2018      N    -32
9   234   2/5/2018      Y      0
10  234  4/10/2018      N    -26
11  234   5/6/2018      Y      0

推荐阅读