python - 当 np.where 无法工作时,可以更快地替代 pandas 数据框中的 apply()
问题描述
我有一个包含 600,000 行的数据框,其中包含一个日期列。问题是这些日期以两种不同格式作为字符串随机输入:
- 非常标准的日期时间格式的字符串,例如“2018-05-07 04:28:45.970”
- UNIX 日期时间格式的字符串,例如“1526366895249000000”(是的,精确到纳秒,但精度不是问题,因为所有条目都以 000000 结尾)
除了这两种格式之外,column 中还有 NaN 值。我正在尝试清理此列并将其转换为统一的日期时间数据类型。
我编写了以下函数来做到这一点:
def date_extractor(dt):
# for UNIX format
if str(dt).isdigit():
return datetime.utcfromtimestamp(int(dt)/1000000000)
# for nan
elif type(dt) == float:
return dt
# for the common datetime format
else:
return datetime.strptime(str(dt), '%Y-%m-%d %H:%M:%S.%f')
这是我对该apply()
函数的调用:
%time df['Date'] = df['Date'].apply(date_extractor)
显然,这是一种非常粗鲁的做法。例如,在上面的函数中,我首先检查了 UNIX 格式,然后检查了 NaN,最后检查了日期时间格式。但是,我的绝大多数日期条目都是日期时间格式。因此,对于日期条目为日期时间格式的循环的每次迭代,循环必须在最终到达最后的 else 语句之前检查前两个 if 语句。因为我不知道如何编写一个非常有效的 if 条件来专门检查日期时间格式,然后再检查 NaN 或 UNIX 格式并且不会导致错误。其次,如您所见,我使用该条件type(dt) == float
来检查 NaN。如果我使用isnan()
或isnull()
,如果日期条目是日期时间格式的字符串,并且仅在最后检查,它将引发错误。
专业人士,有哪些更快、更好的做法可以遵循?
此外,我的代码运行所有 600,000 行大约需要 10 秒。但我也想将我的代码扩展到大约 100 倍大的数据。如何重写我的date_extractor()
函数以更快地完成此任务?我读到一种方法是使用numpy.where()
语句而不是,apply()
但如果以 numpy.where 格式编写,我现有的代码将引发错误。
这是一个演示(嵌套 np.where):
np.where(str(df['Date']).isdigit() == True, datetime.utcfromtimestamp(int(df['Date'])/1000000000),
np.where(type(df['Date']) == float, df['Date'],
datetime.strptime(str(dt), '%Y-%m-%d %H:%M:%S.%f')))
这会引发很多错误——比如调用isdigit()
整列、将整列传递给int()
函数等。
特长; 什么是清理我的日期列的更好方法(或者可能是最好的方法),请记住,我的大多数日期条目都是日期时间字符串格式,例如“2018-05-07 04:28:45.970”,其中一些在像“1526366895249000000”这样的 UNIX 格式,还有几个是 NaN?您可以建议一个更好的代码与我现有的 apply() 函数一起使用,或者完全建议一个不同的方法。
在此处查找示例数据: https ://github.com/verterse/experiments/blob/main/sample.csv
解决方案
单程:
df.date = (
pd.to_datetime(
pd.to_numeric(df.date, errors='coerce'),
unit='ns',
origin='unix')
.fillna(pd.to_datetime(df.date, errors='coerce'))
)
输出(基于样本数据):
VisitDateTime UserID Activity
0 2018-05-15 06:48:15.248999936 U106593 click
1 2018-05-23 07:02:01.790000128 U108297 NaN
2 2018-05-10 06:28:53.391000000 U132443 NaN
3 2018-05-08 12:40:02.153000000 U134616 click
4 2018-05-11 15:35:43.689000000 U130784 click
推荐阅读
- django - Django REST Serializer 使用错误的模型进行序列化
- python - python文件写入程序运行时如何更新桌面上的文件大小
- javascript - 使用 d3.js 更新表数据
- c# - C#捕获从不在进程中的函数返回的异常?
- r - 如何设置仅在输入 3 时才显示集合向量的函数?
- javascript - 如果 URI 没有改变,例如在单页应用程序上,如何检测用户是否在新页面上?
- angular - Angular Kendo UI 全局访问
- php - 内连接循环通过
- git - 如何 git rebase 从另一个分支直接到 master 分支?
- javascript - 受控数字比例映射