目前,我正在创建一系列列,其中包含基于所使用的数据框中的日期的布尔值
df['bool1'] = [1 if x > pd.to_datetime('20190731') else 0 for x in df['date']]
df['bool2'] = [1 if x > pd.to_datetime('20190803') else 0 for x in df['date']]
df['bool3'] = [1 if x > pd.to_datetime('20190813') else 0 for x in df['date']]
我认为这样的列表理解是解决问题的一种Python方法。我觉得我的代码在做什么方面非常清楚,并且有人可以轻松地遵循它。
例如,为{bool1:'20190731'}创建字典,然后循环遍历Key:Value对,这样可能会有所改进,这样我就不再重复代码行了。但这只会减少行数,同时增加可读性和可伸缩性。实际上,这不会使我的代码运行得更快。
但是我的问题是这段代码实际上运行起来很慢。我应该使用lambda函数来加快速度吗?编写此代码最快的方法是什么?
答案 0 :(得分:2)
我认为字典中包含用于比较的值的新列是个好主意。
d = {'bool1':'20190731', 'bool2':'20190803', 'bool3':'20190813'}
然后可以在循环中创建新列:
for k, v in d.items():
df[k] = (df['date'] > pd.to_datetime(v)).astype(int)
#alternative
#df[k] = np.where(df['date'] > pd.to_datetime(v), 1, 0)
为提高性能,请使用numpy广播:
rng = pd.date_range('20190731', periods=20)
df = pd.DataFrame({'date': rng})
d = {'bool1':'20190731', 'bool2':'20190803', 'bool3':'20190813'}
#pandas 0.24+
mask = df['date'].to_numpy()[:, None] > pd.to_datetime(list(d.values())).to_numpy()
#pandas below
#mask = df['date'].values[:, None] > pd.to_datetime(list(d.values())).values
arr = np.where(mask, 1, 0)
df = df.join(pd.DataFrame(arr, columns=d.keys()))
print (df)
date bool1 bool2 bool3
0 2019-07-31 0 0 0
1 2019-08-01 1 0 0
2 2019-08-02 1 0 0
3 2019-08-03 1 0 0
4 2019-08-04 1 1 0
5 2019-08-05 1 1 0
6 2019-08-06 1 1 0
7 2019-08-07 1 1 0
8 2019-08-08 1 1 0
9 2019-08-09 1 1 0
10 2019-08-10 1 1 0
11 2019-08-11 1 1 0
12 2019-08-12 1 1 0
13 2019-08-13 1 1 0
14 2019-08-14 1 1 1
15 2019-08-15 1 1 1
16 2019-08-16 1 1 1
17 2019-08-17 1 1 1
18 2019-08-18 1 1 1
19 2019-08-19 1 1 1
答案 1 :(得分:1)
使用numpy.where
,它应该更快
df['bool1'] = np.where(df['date'] > pd.to_datetime('20190731'), 1, 0)
df['bool2'] = np.where(df['date'] > pd.to_datetime('20190803'), 1, 0)
df['bool3'] = np.where(df['date'] > pd.to_datetime('20190813'), 1, 0)