当一个单元格内有多个值时,计算两列之间的年份差异。

4

请在这方面给我指导。我有一个如下的数据框:

df
    dob         date                                         
1   8/11/1966   3/1/1990, 5/1/2000, 8/1/2010
2   6/13/1970   4/1/2014, 3/1/2016, 4/1/2017
3   10/10/2010  4/13/2017

我的目标是生成一列,显示“dob”和“date”列之间的年份差异,如下所示:

df
    dob         date                            difference                  
1   8/11/1966   3/1/1990, 5/1/2000, 8/1/2010    23.570, 23.740, 23.992
2   6/13/1970   4/1/2014, 3/1/2016, 4/1/2017    43.833, 45.751, 46.836
3   10/10/2010  4/13/2017                       6.512

使用以下代码:
diff = (df['date'].sub(df['dob']))/365
diff = (diff / np.timedelta64(1, 'D')).astype(float)
df['difference'] = diff.round(3)

当只有一个日期时,我能够计算出差异,但是当在一个单元格中存在由逗号分隔的多个值时,无法计算。我该如何实现我的目标?非常感谢。


4
将您的列中的数据分割。如果总是有三个日期,最好的方法可能是将它们分成三列 (df['date1'],df['date2'],df['date3'])。如果有可变数量的日期,则存在问题。您可以通过多行乘法拆分日期 (创建n行与相同数据,除了日期) 或对每个单元格应用Python函数 (可能会很慢,但根据行数而定,您可能不在意)。 - aghast
1个回答

3
考虑数据框架df
df = pd.DataFrame(dict(
        dob=['8/11/1996', '6/13/1970'],
        date=[['3/1/1990', '5/1/2000', '8/1/2010'],
              ['4/1/2014', '3/1/2016', '4/1/2017']]
    )).reindex_axis(['dob', 'date'], 1)

l = df.date.str.len()
ilvl0 = df.index.repeat(l)
ilvl1 = np.concatenate(l.apply(np.arange))
date = pd.Series(
    pd.to_datetime(np.concatenate(df.date.values)),
    [ilvl0, ilvl1]
)

difference = date.sub(
    dob, level=0).dt.days.div(365.25).groupby(level=0).apply(list)
df.assign(difference=difference)

         dob                            date            difference
0  8/11/1996  [3/1/1990, 5/1/2000, 8/1/2010]  [-6.45, 3.72, 13.97]
1  6/13/1970  [4/1/2014, 3/1/2016, 4/1/2017]   [43.8, 45.72, 46.8]

旧答案

该答案已经过时。
date_df = pd.to_datetime(
    pd.DataFrame(df.date.values.tolist(), df.index).stack()
 ).unstack()

一点魔法和...
df.assign(
    difference=date_df.sub(
        pd.to_datetime(df.dob), 0
    ).stack().dt.days.groupby(level=0).apply(list)
)

         dob                            date             difference
0 1996-08-11  [3/1/1990, 5/1/2000, 8/1/2010]    [-2355, 1359, 5103]
1 1970-06-13  [4/1/2014, 3/1/2016, 4/1/2017]  [15998, 16698, 17094]

如果你想要以年为单位而不是天:
df.assign(
    difference=date_df.sub(
        pd.to_datetime(df.dob), 0
    ).stack().apply(lambda x: x.days / 365.25).round(2).groupby(level=0).apply(list)
)

         dob                            date            difference
0  8/11/1996  [3/1/1990, 5/1/2000, 8/1/2010]  [-6.45, 3.72, 13.97]
1  6/13/1970  [4/1/2014, 3/1/2016, 4/1/2017]   [43.8, 45.72, 46.8]

谢谢您的回答!由于我的df ['date']中的数据类型是字符串而不是列表,因此最好的方法是将其更改为列表,就像您的数据框中所看到的那样。提前致谢。 - Henry
1
请提前运行以下代码:df.date = df.date.str.split(',\s*') - piRSquared

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接