You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas高效实现:将DataFrame数值追加到另一DataFrame列表列对应行

问题描述

现有两个通过如下代码创建的DataFrame:

df1
       Fecha Vals
0 2001-01-01   []
1 2001-01-02   []
2 2001-01-03   []
3 2001-01-04   []
4 2001-01-05   []
5 2001-01-06   []
6 2001-01-07   []
7 2001-01-08   []
8 2001-01-09   []

df2
       Fecha  Vals
0 2001-01-01   0.0
1 2001-01-03   1.0
2 2001-01-05   2.0
3 2001-01-07   3.0
4 2001-01-09   4.0

需要将df2中的Vals值追加到df1中对应Fecha行的Vals列表里,得到如下结果:

df1
       Fecha Vals
0 2001-01-01   [0.0]
1 2001-01-02   []
2 2001-01-03   [1.0]
3 2001-01-04   []
4 2001-01-05   [2.0]
5 2001-01-06   []
6 2001-01-07   [3.0]
7 2001-01-08   []
8 2001-01-09   [4.0]

尝试用for循环实现,但面对大型DataFrame时速度极慢,希望找到无需循环的高效实现方式。目前已能用df1['Fecha'].isin(df2['Fecha'].values)筛选df1中的对应行。

补充说明

  • 后续需重复此操作,将df3等DataFrame的数值追加到df1的其他行中,且不希望去重。例如df3 = pd.DataFrame({'Fecha': ['2001-01-02', '2001-01-05', '2001-01-08'], 'Vals': [0.0, 1.0, 2.0]})。
  • df2中的间隔仅为示例构造情况。
  • 完成追加操作后,需为每行创建均值列和标准差列。
  • 创建DataFrame的完整代码:
import datetime
import pandas as pd
yy = 2001
date_list = ['{:4d}-{:02d}-{:02d}'.format(yy, mm, dd) for mm in range(1, 2) for dd in range(1, 10)]
fechas1 = [datetime.datetime.strptime(date_base, '%Y-%m-%d') for date_base in date_list]
nf1 = len(fechas1)
vals1 = [[] for _ in range(nf1)]
dic1 = { 'Fecha': fechas1, 'Vals': vals1 }
df1 = pd.DataFrame(dic1)
fechas2 = [datetime.datetime.strptime(date_list[idx], '%Y-%m-%d') for idx in range(0, nf1, 2)]
nf2 = len(fechas2)
vals2 = [float(idx) for idx in range(nf2)]
dic2 = { 'Fecha': fechas2, 'Vals': vals2 }
df2 = pd.DataFrame(dic2)
高效实现方案

1. 单次追加(df2到df1)

利用字典查询+批量更新的方式,避免逐行循环:

# 将df2转为日期到值的映射字典
date_to_val = df2.set_index('Fecha')['Vals'].to_dict()

# 批量更新df1的Vals列:匹配到日期则追加值,否则保留原列表
df1['Vals'] = df1.apply(
    lambda row: row['Vals'] + [date_to_val[row['Fecha']]] if row['Fecha'] in date_to_val else row['Vals'],
    axis=1
)

字典查询为O(1)操作,apply基于向量化逻辑执行,效率远高于for循环。

2. 多次追加(支持df3、df4等)

封装成函数,方便重复调用:

def append_vals_to_df1(df_target, df_source):
    date_to_val = df_source.set_index('Fecha')['Vals'].to_dict()
    df_target['Vals'] = df_target.apply(
        lambda row: row['Vals'] + [date_to_val[row['Fecha']]] if row['Fecha'] in date_to_val else row['Vals'],
        axis=1
    )
    return df_target

# 示例:追加df2
df1 = append_vals_to_df1(df1, df2)
# 追加df3
df3 = pd.DataFrame({'Fecha': ['2001-01-02', '2001-01-05', '2001-01-08'], 'Vals': [0.0, 1.0, 2.0]})
df1 = append_vals_to_df1(df1, df3)

执行后df1中2001-01-05行的Vals会变为[2.0, 1.0],满足不重复追加的需求。

3. 计算均值和标准差列

对每行的Vals列表计算统计值,空列表或单元素列表返回NaN:

import numpy as np

df1['Mean'] = df1['Vals'].apply(lambda x: np.mean(x) if x else np.nan)
# 样本标准差(ddof=1),至少2个值才计算
df1['Std'] = df1['Vals'].apply(lambda x: np.std(x, ddof=1) if len(x)>=2 else np.nan)

若需计算总体标准差,去掉ddof=1参数即可。

超大型DataFrame性能优化

如果数据量达到百万级以上,可采用完全向量化的合并方式,进一步提升性能:

# 将df2的单个值转为列表格式,方便合并
df2_list = df2.assign(Vals=df2['Vals'].apply(lambda x: [x]))
# 合并df1与df2,空值用原列表填充
merged = df1.merge(df2_list, on='Fecha', how='left', suffixes=('', '_new'))
df1['Vals'] = merged['Vals_new'].combine_first(merged['Vals']).apply(lambda x: x if isinstance(x, list) else [])

内容的提问来源于stack exchange,提问作者sancho.s ReinstateMonicaCellio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 07:25:14