日期计算(TypeError:不支持的操作数类型“ str”和“ str”)

4
我有以下数据集:

        date_time       srch_co     srch_ci
0   2014-11-03 16:02:28 2014-12-19  2014-12-15
1   2013-03-13 19:25:01 2013-03-14  2013-03-13
2   2014-10-13 13:20:25 2015-04-10  2015-04-03
3   2013-11-05 10:40:34 2013-11-08  2013-11-07
4   2014-06-10 13:34:56 2014-08-08  2014-08-03
5   2014-12-16 14:34:39 2014-12-17  2014-12-16

这是数据集的信息:

     <class 'pandas.core.frame.DataFrame'>
RangeIndex: 100000 entries, 0 to 99999
Data columns (total 3 columns):
date_time    100000 non-null datetime64[ns]
srch_co      99878 non-null object
srch_ci      99878 non-null object
dtypes: datetime64[ns](1), object(2)
memory usage: 2.3+ MB

我希望做的是使用以下函数创建2个新列:
def duration(row):
    delta = (row['srch_co'] - row['srch_ci'])/np.timedelta64(1, 'D')
    if delta <= 0:
        return np.nan
    else:
        return delta

sample['duration'] = sample.apply(duration, axis=1)


def days_in_advance(row):
    delta = (row['srch_ci'] - row['date_time'])/np.timedelta64(1, 'D')
    if delta < 0:
        return np.nan
    else:
        return delta

sample['days_in_advance'] = sample.apply(days_in_advance, axis=1)

然而,似乎我想运行的日期计算经常出错。我搜索并找到了几个解决方案并尝试过,但要么会创建错误,要么将日期转换为不准确的值。
我尝试使用的方法包括:
#1)
def to_integer(dt_time):
    return 10000*dt_time.year + 100*dt_time.month + dt_time.day

#2)
datetime.strptime(str(row[2]), '%Y%m%d%H%M%S')

#3)    
pd.to_numeric(sample['date_time'], errors='coerce')

#4)
sample['srch_ci_int'] = sample['srch_ci'].astype(str).astype(int)

我只想创建一个新的列来计算每一列之间的差异:

sample["duration"] = sample["srch_co"] - sample["srch_ci"]
sample["days_in_advance"] = sample["srch_co"] - sample["date_time"]

任何提示都会受到赞赏。

从我们这里获得的信息来看,我认为将“srch_*”列转换为“datetime”对象可能会有所帮助。 - Marvin Taschenberger
好的,我不知道为什么我没有想到那个。谢谢!sample['srch_co'] = pd.to_datetime(sample['srch_co']) sample['srch_ci'] = pd.to_datetime(sample['srch_ci'])这个有效。 - tmhs
2个回答

7
你需要首先将列 srch_cosrch_ci to_datetime 转换,然后使用 mask 替换小于 0 的值为 NaNmask 函数的默认值):
sample["srch_co"] = pd.to_datetime(sample["srch_co"])
sample["srch_ci"] = pd.to_datetime(sample["srch_ci"])

sample["duration"] = (sample["srch_co"] - sample["srch_ci"])/np.timedelta64(1, 'D')
sample["days_in_advance"] = (sample["srch_co"] - sample["date_time"])/np.timedelta64(1, 'D')

cols = ['duration','days_in_advance']
sample[cols] = sample[cols].mask(sample[cols] < 0)
#first value of srch_ci column was changed for NaN output
print (sample)
            date_time    srch_co    srch_ci  duration  days_in_advance
0 2014-11-03 16:02:28 2014-12-19 2015-12-15       NaN        45.331620
1 2013-03-13 19:25:01 2013-03-14 2013-03-13       1.0         0.190961
2 2014-10-13 13:20:25 2015-04-10 2015-04-03       7.0       178.444155
3 2013-11-05 10:40:34 2013-11-08 2013-11-07       1.0         2.555162
4 2014-06-10 13:34:56 2014-08-08 2014-08-03       5.0        58.434074
5 2014-12-16 14:34:39 2014-12-17 2014-12-16       1.0         0.392604

1
看起来你正在从一个字符串中减去另一个字符串。请确保使用 pd.to_datetime 将列转换为“日期”类型,然后就可以相减一天了。
另一个建议是避免使用for循环,而是使用向量化操作,例如 pd.DataFrame.subtract(series, axis=0),因为这是使用pandas比使用任何简单列表的最大优势之一。
在计算出差异之后,你可以通过以下方式将所有负数变成nan:
dataframe[dataframe['duration'] < 0] = np.nan

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