一个单独的列(通常)是一个 pandas Series,正如
EdChum 所提到的,
DataFrame.apply
有
axis
参数,但
Series.apply
没有,所以在
axis=1
上使用
apply
将不会对列起作用。
以下代码可以正常工作:
df['col'].apply(lambda x, y: (x - y).total_seconds(), args=(d1,))
如果要对行中的每个元素应用一个函数,也可以使用map
:
df['col'].map(lambda x: (x - d1).total_seconds())
由于apply
只是Python循环的语法糖,所以列表推导式可能比它们都更有效率,因为它没有pandas的开销:
[(x - d1).total_seconds() for x in df['col'].tolist()]
对于单列DataFrame,可以传递
axis=1
:
df[['col']].apply(lambda x, y: (x - y).dt.total_seconds(), args=[d1], axis=1)
注意:如果可以的话,请避免使用apply
apply
在大多数情况下甚至都不需要。对于OP中的情况(以及大多数其他情况),存在一种向量化操作(只需从列中减去d1
- 值会广播以匹配列),而且比apply
快得多:
(df['col'] - d1).dt.total_seconds()
时间
向量化的减法比在列上使用apply
快约150倍,在只有一列的DataFrame上使用apply
快7000多倍,对于一个有1万行的数据框。由于apply
是一个循环,随着行数的增加,这个差距会越来越大。
df = pd.DataFrame({'col': pd.date_range('2000', '2023', 10_000)})
d1 = df['col'].min()
%timeit df['col'].apply(lambda x, y: (x - y).total_seconds(), args=[d1])
%timeit df['col'].map(lambda x: (x - d1).total_seconds())
%timeit [(x - d1).total_seconds() for x in df['col'].tolist()]
%timeit (df['col'] - d1).dt.total_seconds()
%timeit df[['col']].apply(lambda x, y: (x - y).dt.total_seconds(), args=[d1], axis=1)