如何用DataFrame的Hour列修改Datetime小时并处理异常值?
问题解决:处理DataFrame中带异常值的日期列转换及通用编辑方法
我有如下结构的DataFrame,Day列大部分是d-m-y格式的日期,但存在异常值(比如示例中的"7"):
import pandas as pd AL = [ ['1','10-12-2022','2022-12-17 00:00:00'], ['1','10-12-2022','2022-12-17 00:00:00'], ['1','7','2022-12-17 00:00:00'] ] df_long = pd.DataFrame(AL, columns=['Hour','Day','Day2'])
各列数据类型均为object:
Day object Day2 object Hour object dtype: object
需求是将Day列的正常日期条目替换小时为Hour列的数值,生成格式为dd-mm-yyyy HH:MM:SS的新列,但直接用pd.to_datetime转换会因异常值报错:
df_long['Day3']= pd.to_datetime(df_long['Day']) + pd.to_timedelta(df_long['Hour'])
报错信息:
error: time data "7" doesn't match format "%d-%m-%Y", at position 6. You might want to try: - passing `format` if your strings have a consistent format;
分步解决异常值问题并生成目标列
- 筛选有效日期行:用正则表达式匹配
d-m-y格式的日期,生成布尔索引定位正常条目 - 转换并调整时间:对有效日期转换为datetime类型,加上Hour列对应的小时数
- 格式化输出:将调整后的datetime格式化为目标字符串格式,异常值可设为
NaN或保留原内容
代码实现:
# 1. 匹配d-m-y格式的日期,生成布尔索引 valid_dates = df_long['Day'].str.match(r'^\d{1,2}-\d{1,2}-\d{4}$') # 2. 初始化Day3列为空值(若要保留异常值原内容,改为df_long['Day3'] = df_long['Day']) df_long['Day3'] = pd.NA # 3. 处理有效日期行:转换日期+添加小时+格式化 df_long.loc[valid_dates, 'Day3'] = ( pd.to_datetime(df_long.loc[valid_dates, 'Day'], format='%d-%m-%Y') + pd.to_timedelta(df_long.loc[valid_dates, 'Hour'].astype(int), unit='h') ).dt.strftime('%d-%m-%Y %H:%M:%S')
输出结果:
| Hour | Day | Day2 | Day3 |
|---|---|---|---|
| 1 | 10-12-2022 | 2022-12-17 00:00:00 | 10-12-2022 01:00:00 |
| 1 | 10-12-2022 | 2022-12-17 00:00:00 | 10-12-2022 01:00:00 |
| 1 | 7 | 2022-12-17 00:00:00 |
DataFrame中选择并编辑特定条目的通用方法
1. 布尔索引筛选(最常用)
用df.loc[布尔条件, 目标列]定位符合要求的行,直接赋值修改:
# 示例:筛选Day列长度大于5的行,修改Day3 df_long.loc[df_long['Day'].str.len() > 5, 'Day3'] = '处理后的值'
2. 正则匹配筛选
针对字符串列,用str.match/str.contains精准匹配格式或内容:
# 匹配包含数字和连字符的日期格式行 target_rows = df_long['Day'].str.contains(r'\d+-\d+-\d+') df_long.loc[target_rows, 'Day3'] = '匹配到的内容'
3. where/mask 方法
where:满足条件保留原值,不满足则替换为指定值mask:与where相反,不满足条件保留原值,满足则替换
# 示例:有效日期保留处理后的值,否则设为NaN df_long['Day3'] = (pd.to_datetime(df_long['Day'], format='%d-%m-%Y', errors='coerce') + pd.to_timedelta(df_long['Hour'].astype(int), unit='h') ).dt.strftime('%d-%m-%Y %H:%M:%S').where(valid_dates, pd.NA)
4. apply结合自定义函数
对每行应用自定义逻辑,灵活处理复杂判断:
def process_row(row): # 判断Day是否为有效日期 if pd.Series(row['Day']).str.match(r'^\d{1,2}-\d{1,2}-\d{4}$').iloc[0]: return (pd.to_datetime(row['Day'], format='%d-%m-%Y') + pd.to_timedelta(int(row['Hour']), unit='h')).strftime('%d-%m-%Y %H:%M:%S') else: return pd.NA df_long['Day3'] = df_long.apply(process_row, axis=1)
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

