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

基于两个数据框计算不同组合均值的R语言实现问题

问题解决:匹配多ID的时间序列数据并计算均值

需求明确

  • 你有两个DataFrame:
    • df1:包含列v1、v2、v3(存储需要匹配的ID值)
    • df2:包含列ID、Days、Hours、BT,每个ID对应7天,每天24小时的BT数据
  • 目标:对df1的每一行,匹配df2中相同Days、Hours组合下v1、v2、v3对应的BT值,计算这三个值的均值,最终生成包含v1、v2、v3、Days、Hours、Mean_BT的结果表

测试数据生成

先给出可复现的测试数据代码:

import pandas as pd
import numpy as np

# 生成df2:每个ID覆盖7天×24小时的BT数据
ids = [101, 102, 103, 104, 105]
days = range(1, 8)
hours = range(0, 24)

df2_data = []
for id_val in ids:
    for day in days:
        for hour in hours:
            df2_data.append({
                'ID': id_val,
                'Days': day,
                'Hours': hour,
                'BT': np.random.uniform(36.0, 37.5)
            })
df2 = pd.DataFrame(df2_data)

# 生成df1:随机生成v1/v2/v3的ID组合
np.random.seed(42)
df1 = pd.DataFrame({
    'v1': np.random.choice(ids, 10),
    'v2': np.random.choice(ids, 10),
    'v3': np.random.choice(ids, 10)
})

常见循环错误原因

你之前的循环代码出错,大概率是以下问题:

  • 没有给df1的每一行匹配所有Days、Hours组合,只处理了单一时间点
  • 匹配ID时没有同时锁定Days和Hours条件,导致取错BT值
  • 均值计算时没有正确聚合三个ID对应的BT值

正确实现方法

方法一:索引映射+交叉连接

利用索引快速查找BT值,结合交叉连接覆盖所有时间组合:

# 把df2转成多层索引,方便按Days/Hours/ID快速定位BT值
bt_lookup = df2.set_index(['Days', 'Hours', 'ID'])['BT']

# 生成Days和Hours的全组合,用于和df1做交叉连接
time_combinations = pd.MultiIndex.from_product([days, hours], names=['Days', 'Hours']).to_frame(index=False)

# 交叉连接:让df1的每一行ID组合匹配所有时间点
df1_expanded = df1.merge(time_combinations, how='cross')

# 定义函数计算单一行的均值
def get_mean_bt(row):
    # 分别获取三个ID在当前时间点的BT值
    bt1 = bt_lookup.get((row['Days'], row['Hours'], row['v1']), np.nan)
    bt2 = bt_lookup.get((row['Days'], row['Hours'], row['v2']), np.nan)
    bt3 = bt_lookup.get((row['Days'], row['Hours'], row['v3']), np.nan)
    # 计算均值,自动忽略缺失值
    return np.mean([bt1, bt2, bt3])

# 应用函数生成均值列
df1_expanded['Mean_BT'] = df1_expanded.apply(get_mean_bt, axis=1)

# 提取最终结果
result = df1_expanded[['v1', 'v2', 'v3', 'Days', 'Hours', 'Mean_BT']]
print(result.head())

方法二:宽表转换+合并计算

把df2转成宽表后直接匹配计算,代码更简洁:

# 将df2转换为宽表:Days/Hours为索引,ID为列,值为BT
df2_wide = df2.pivot_table(index=['Days', 'Hours'], columns='ID', values='BT').reset_index()

# 交叉连接df1和时间组合(同方法一)
time_combinations = pd.MultiIndex.from_product([days, hours], names=['Days', 'Hours']).to_frame(index=False)
df1_expanded = df1.merge(time_combinations, how='cross')

# 合并宽表,获取每个ID对应的BT值
merged_df = df1_expanded.merge(df2_wide, on=['Days', 'Hours'], how='left')

# 计算三个ID的BT均值
merged_df['Mean_BT'] = merged_df.apply(lambda row: np.mean([row[row['v1']], row[row['v2']], row[row['v3']]]), axis=1)

# 提取结果
result = merged_df[['v1', 'v2', 'v3', 'Days', 'Hours', 'Mean_BT']]
print(result.head())

关键注意事项

  • 必须做交叉连接:因为每个ID对应所有7天24小时的数据,所以df1的每一行ID组合需要匹配所有时间点
  • 匹配条件要完整:必须同时指定Days、Hours、ID三个维度,避免取错数据
  • 缺失值处理:如果某个ID在对应时间点没有数据,用np.nan填充,np.mean会自动忽略缺失值(如果需要强制计算包含缺失值,改用np.nanmean)

内容的提问来源于stack exchange,提问作者Usman YousafZai

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 10:10:39