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

如何合并含共享列的ROOT DataFrame并保存至同一ROOT文件?

问题描述

我用同事编写的代码模拟事件,输出了一个.root文件。分析时我读取其中的TTree,通过自定义Python函数生成多个numpy数组,再把这些输出转换成独立的ROOT DataFrame。现在想知道:能不能合并这两个包含共享列的DataFrame,得到一个整合了双方数据的DataFrame?如果不可行,另一种方案是把我的列作为分支添加到原ROOT文件的树中。我刚接触ROOT,希望能得到清晰的方案。

最终目标是把我和同事的数据整合到同一个.root文件中。两个DataFrame共享EventNumber列(每个事件唯一)和Asic列(不唯一),这两列无需重复添加,且数据顺序已经对应正确。

相关代码如下:

import ROOT as r
import numpy as np
import pandas as pd

df = r.RDataFrame('tree',"~/FirstOutput.root")

board = np.zeros(tree.GetEntries(),dtype='int')
column = np.zeros(tree.GetEntries(),dtype='int')

ASIC_Column = []
EventNumn = []

for event in range(tree.GetEntries()):
    tree.GetEntry(event)
    asic= tree.asic[0]
    event_Numn = tree.eventNumber
    ASIC_Column.append(asic)
    EventNumn.append(event_Numn)
    board[event] = get_board(asic)
    column[event] = is_even(asic)

# Board和Column是从原DataFrame的Asic列生成的numpy数组
# get_board和is_even用于判断事件在探测器上的位置

d = pd.DataFrame()
d['board'] = board
d['column'] = column
d['asic'] = ASIC_Column
d['eventNumber'] = EventNumn
data = {key: d[key].values for key in ['eventNumber', 'asic', 'board','column']}
rdf = r.RDF.FromNumpy(data)
解决方案

方案一:直接在原RDataFrame上生成新列(最推荐)

你当前的循环读TTree效率很低,ROOT RDataFrame支持直接在原数据集上用Define方法生成新列,无需手动转numpy再新建RDataFrame,一步就能得到整合所有数据的DataFrame,之后直接导出即可。

示例代码:

import ROOT as r

# 读取原ROOT文件的树
df = r.RDataFrame('tree', "~/FirstOutput.root")

# 定义自定义函数,适配RDataFrame的列数据格式(asic是数组,取第一个元素)
def get_board(asic_array):
    asic = asic_array[0]
    # 替换成你的实际get_board逻辑
    return asic // 10  

def is_even(asic_array):
    asic = asic_array[0]
    # 替换成你的实际is_even逻辑
    return 1 if asic % 2 == 0 else 0  

# 在原DataFrame上添加新列
df_with_new_cols = df.Define("board", get_board, ["asic"])\
                    .Define("column", is_even, ["asic"])

# 导出到新的ROOT文件,包含所有原列和新列
df_with_new_cols.Snapshot("tree", "MergedOutput.root")

方案二:合并两个已有的RDataFrame

如果你已经生成了两个独立的RDataFrame(原df和自己创建的rdf),可以通过Join操作合并,用唯一标识eventNumber作为连接键:

# 先移除自己生成的rdf中重复的列(比如asic),避免合并后重复
rdf_clean = rdf.DropColumns(["asic"])
# 以eventNumber为键合并两个DataFrame
merged_df = df.Join(rdf_clean, "eventNumber")

# 导出整合后的数据集到新文件
merged_df.Snapshot("tree", "MergedOutput.root")

方案三:将新列添加到原ROOT文件的树中

如果需要直接给原树添加分支(或生成包含原树+新分支的新文件),可以直接操作TTree:

import ROOT as r
import numpy as np

# 打开原文件(只读模式)
input_file = r.TFile("~/FirstOutput.root", "READ")
tree = input_file.Get("tree")

# 新建输出文件
output_file = r.TFile("UpdatedOutput.root", "RECREATE")
# 复制原树的结构,但不复制数据
new_tree = tree.CloneTree(0)

# 定义要添加的分支变量
board = np.zeros(1, dtype='int')
column = np.zeros(1, dtype='int')

# 给新树添加分支
new_tree.Branch("board", board, "board/I")
new_tree.Branch("column", column, "column/I")

# 遍历原树,计算并填充新分支
for event in tree:
    asic = event.asic[0]
    board[0] = get_board(asic)
    column[0] = is_even(asic)
    new_tree.Fill()

# 写入数据并关闭文件
new_tree.Write()
output_file.Close()
input_file.Close()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 19:04:52