如何在numpy.where()中快速将字符串日期NumpyArray转为datetime变量
解决方案
首先,datetime.strptime()只能处理单个字符串,无法直接作用于numpy数组或pandas Series,这是你代码失败的核心原因。推荐用pandas的pd.to_datetime()批量转换日期字符串,它能高效处理数组级别的转换,还能自动处理无效值。
以下是完整的实现步骤:
1. 转换日期列并处理无效值
先把Info_Date和Login_Date转换为datetime类型,用errors='coerce'将无效值(包括空字符串、'Invalid date')转为NaT(Not a Time),方便后续判断:
import pandas as pd from datetime import datetime, timedelta import numpy as np source_data = pd.read_excel("./documents/data.xlsx") # 计算阈值日期 three_months_ago = datetime.now() - timedelta(days=90) thirty_days_ago = datetime.now() - timedelta(days=30) # 批量转换日期列,处理无效值 date_format = "%d/%m/%Y %H:%M" source_data['Info_Date_dt'] = pd.to_datetime(source_data['Info_Date'], format=date_format, errors='coerce') source_data['Login_Date_dt'] = pd.to_datetime(source_data['Login_Date'], format=date_format, errors='coerce')
2. 构建筛选条件
按你的需求,构建三个布尔条件:
- 条件1:
Info_Date或Login_Date是'Invalid date' - 条件2:转换后的
Info_Date_dt早于3个月前 - 条件3:转换后的
Login_Date_dt早于30天前
将这三个条件用逻辑或(|)组合:
# 条件1:存在无效日期字符串 cond_invalid = (source_data['Info_Date'] == 'Invalid date') | (source_data['Login_Date'] == 'Invalid date') # 条件2:Info_Date早于3个月前(排除NaT值) cond_info_old = (source_data['Info_Date_dt'] < three_months_ago) & source_data['Info_Date_dt'].notna() # 条件3:Login_Date早于30天前(排除NaT值) cond_login_old = (source_data['Login_Date_dt'] < thirty_days_ago) & source_data['Login_Date_dt'].notna() # 合并所有条件 final_cond = cond_invalid | cond_info_old | cond_login_old
3. 用numpy.where筛选数据
如果你坚持要用numpy.where()获取索引并筛选,可以这样做:
# 获取符合条件的行索引 indices = np.where(final_cond)[0] # 筛选数据 filtered_data = source_data.iloc[indices][['Serials', 'Info_Date', 'Login_Date']] print(filtered_data)
运行后会得到包含符合条件的结果:
| Serials | Info_Date | Login_Date |
|---|---|---|
| SNXXXXX1 | 29/02/2024 13:40 | 10/02/2024 10:00 |
| SNXXXXX4 | Invalid date |
(注:SNXXXXX4因为符合条件1也会被筛选,若不需要该结果,可调整条件1的判断逻辑)
补充说明
pd.to_datetime()比手动循环转换效率高得多,适合大数据集处理- 加入
notna()判断是为了避免NaT与日期比较时产生的无效结果 - 若不需要保留原日期列,可直接覆盖原列以减少内存占用
内容的提问来源于stack exchange,提问作者user14476651
相关产品推荐
相关产品推荐

