如何用Pandas将子DataFrame替换为另一个子DataFrame?是否可使用where方法实现?
解决方案:替换Pandas DataFrame指定时段数据并保留原日期时间
没问题,我来帮你搞定这个需求!首先我们明确核心目标:替换df1中00:10到00:30时段的行数据为df2对应时段的值,但保留df1原有的DateTime日期。下面分两种方法实现,包括你问到的where方法。
步骤1:准备测试数据
先把你提供的df1和df2用Pandas创建出来,方便后续测试:
import pandas as pd # 创建df1(2019年数据) df1_data = { 'DateTime': ['2019-10-14 00:00:00', '2019-10-14 00:10:00', '2019-10-14 00:20:00', '2019-10-14 00:30:00', '2019-10-14 00:40:00'], 'Col1': [5.35, 4.90, 4.80, 5.12, 5.83], 'Col2': [201.75, 187.65, 186.89, 177.48, 332.94], 'Col3': [16.50, 16.49, 16.48, 16.46, 6.45] } df1 = pd.DataFrame(df1_data) df1['DateTime'] = pd.to_datetime(df1['DateTime']) # 创建df2(2020年数据) df2_data = { 'DateTime': ['2020-10-14 00:00:00', '2020-10-14 00:10:00', '2020-10-14 00:20:00', '2020-10-14 00:30:00', '2020-10-14 00:40:00'], 'Col1': [5.35, 6.90, 6.80, 7.12, 5.83], 'Col2': [231.75, 217.15, 181.69, 175.48, 212.95], 'Col3': [14.50, 14.49, 14.46, 14.48, 15.45] } df2 = pd.DataFrame(df2_data) df2['DateTime'] = pd.to_datetime(df2['DateTime'])
方法一:直接定位赋值(最直观)
这种方法逻辑简单,直接筛选出需要替换的行,然后把df2对应时段的数据赋值过去:
# 定义需要替换的时间范围(只看时分秒,忽略日期) start_time = pd.to_datetime('00:10:00').time() end_time = pd.to_datetime('00:30:00').time() # 筛选df1中需要替换的行 mask_df1 = (df1['DateTime'].dt.time >= start_time) & (df1['DateTime'].dt.time <= end_time) # 筛选df2中对应时段的行 mask_df2 = (df2['DateTime'].dt.time >= start_time) & (df2['DateTime'].dt.time <= end_time) # 提取df2的替换数据(只取数值列) replace_values = df2.loc[mask_df2, ['Col1', 'Col2', 'Col3']].values # 赋值给df1的对应行,保留原DateTime df1.loc[mask_df1, ['Col1', 'Col2', 'Col3']] = replace_values
执行后,df1就会完全符合你的预期结果——原2019年的DateTime保留,00:10-00:30时段的数值被替换为df2的对应值。
方法二:使用Pandas的where方法实现
当然可以用where方法!不过where的逻辑是条件为True时保留原值,False时替换,所以我们需要反向设置条件:
# 同样定义时间范围 start_time = pd.to_datetime('00:10:00').time() end_time = pd.to_datetime('00:30:00').time() mask_df1 = (df1['DateTime'].dt.time >= start_time) & (df1['DateTime'].dt.time <= end_time) mask_df2 = (df2['DateTime'].dt.time >= start_time) & (df2['DateTime'].dt.time <= end_time) # 把df2的替换数据重置索引,确保和df1的筛选行顺序对齐 df2_replacement = df2.loc[mask_df2, ['Col1', 'Col2', 'Col3']].reset_index(drop=True) # 使用where:非替换时段保留df1原值,替换时段用df2的值 df1[['Col1', 'Col2', 'Col3']] = df1[['Col1', 'Col2', 'Col3']].where(~mask_df1, df2_replacement.values)
这里的关键是用~mask_df1取反条件,让需要替换的行触发替换逻辑,同时通过reset_index保证df2的替换数据和df1的目标行顺序一致。
两种方法对比
- 直接赋值法:代码更简洁,逻辑直观,适合这种明确的批量替换场景,推荐优先使用。
where方法:适合需要同时处理"保留/替换"两种逻辑的复杂场景,灵活性更强,但需要注意条件的反向设置和数据对齐。
内容的提问来源于stack exchange,提问作者Fluxy
相关产品推荐
相关产品推荐

