【问题标题】:uproot: processing a TH2D using the uproot method .pandas()uproot:使用 uproot 方法 .pandas() 处理 TH2D
【发布时间】:2020-12-26 15:37:24
【问题描述】:

我对 uproot 和 Python 非常陌生,但希望能很快赶上。 我想知道为什么 .pandas() 方法会从 TH2D 直方图创建这样一个奇怪的表:

myhisto = file["angular_distr_el/ID3_mol_e0_valid/EN_gate/check_cthetaEE_x"]
type(myhisto)

输出:

uproot.rootio.TH2D

最后,myhisto.pandas() 返回:

        count   variance
cos(theta)  electron energy [eV]        
[-inf, -1.0)    [-inf, 10.0)    0.0 0.0
[10.0, 10.15)   0.0 0.0
[10.15, 10.3)   0.0 0.0
[10.3, 10.45)   0.0 0.0
[10.45, 10.6)   0.0 0.0
... ... ... ...
[1.0, inf)  [24.4, 24.549999999999997)  0.0 0.0
[24.549999999999997, 24.7)  0.0 0.0
[24.7, 24.85)   0.0 0.0
[24.85, 25.0)   0.0 0.0
[25.0, inf) 0.0 0.0
2244 rows × 2 columns

myhisto.columns 返回:

Index(['count', 'variance'], dtype='object')

我在哪里可以找到方法.pandas() 的文档以了解它在做什么?有没有办法用正确的列在 DataFrame 中重新组织 myhisto

【问题讨论】:

标签: uproot


【解决方案1】:

经过一些有趣但绝望的浏览后,我明白了它是哪种类型的对象。这是创建 sorted MultiIndex DataFrames 的一种非常聪明的方法。只需输入 myhisto.index 即可直接查看:

MultiIndex([([-inf, -1.0),                [-inf, 10.0)),
            ([-inf, -1.0),               [10.0, 10.15)),
            ([-inf, -1.0),               [10.15, 10.3)),
            ([-inf, -1.0),               [10.3, 10.45)),
            ([-inf, -1.0),               [10.45, 10.6)),
            ([-inf, -1.0),               [10.6, 10.75)),
            ([-inf, -1.0),               [10.75, 10.9)),
            ([-inf, -1.0),               [10.9, 11.05)),
            ([-inf, -1.0),               [11.05, 11.2)),
            ([-inf, -1.0),               [11.2, 11.35)),
            ...
            (  [1.0, inf), [23.65, 23.799999999999997)),
            (  [1.0, inf), [23.799999999999997, 23.95)),
            (  [1.0, inf),               [23.95, 24.1)),
            (  [1.0, inf),               [24.1, 24.25)),
            (  [1.0, inf),               [24.25, 24.4)),
            (  [1.0, inf),  [24.4, 24.549999999999997)),
            (  [1.0, inf),  [24.549999999999997, 24.7)),
            (  [1.0, inf),               [24.7, 24.85)),
            (  [1.0, inf),               [24.85, 25.0)),
            (  [1.0, inf),                 [25.0, inf))],
           names=['cos(theta)', 'electron energy [eV]'], length=2244)

解决方案是拆开或创建 DataFrame 的数据透视表。对于这个特定对象,数据透视表更好,因为在原始 DataFrame 中存在计数和方差作为列。举个例子:

myhisto.unstack()

count   ... variance
electron energy [eV]    [-inf, 10.0)    [10.0, 10.15)   [10.15, 10.3)   [10.3, 10.45)   [10.45, 10.6)   [10.6, 10.75)   [10.75, 10.9)   [10.9, 11.05)   [11.05, 11.2)   [11.2, 11.35)   ... [23.65, 23.799999999999997) [23.799999999999997, 23.95) [23.95, 24.1)   [24.1, 24.25)   [24.25, 24.4)   [24.4, 24.549999999999997)  [24.549999999999997, 24.7)  [24.7, 24.85)   [24.85, 25.0)   [25.0, inf)
cos(theta)                                                                                  
[-inf, -1.0)    0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
[-1.0, -0.9)    0.0 1.0 1.0 0.0 0.0 2.0 0.0 2.0 0.0 1.0 ... 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
[-0.9, -0.8)    0.0 0.0 3.0 3.0 0.0 0.0 0.0 0.0 1.0 1.0 ... 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 0.0
[-0.8, -0.7)    0.0 0.0 1.0 2.0 0.0 1.0 1.0 2.0 1.0 1.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
[-0.7, -0.6)    0.0 0.0 1.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 ... 1.0 1.0 0.0 1.0 1.0 0.0 0.0 1.0 0.0 0.0
[-0.6, -0.5)    0.0 1.0 1.0 1.0 0.0 0.0 2.0 1.0 0.0 3.0 ... 0.0 1.0 0.0 1.0 1.0 

**22 rows × 204 columns**

对比

pivot_pipanda = pipanda.pivot_table(values="count", index="cos(theta)", columns="electron energy [eV]")

electron energy [eV]    [-inf, 10.0)    [10.0, 10.15)   [10.15, 10.3)   [10.3, 10.45)   [10.45, 10.6)   [10.6, 10.75)   [10.75, 10.9)   [10.9, 11.05)   [11.05, 11.2)   [11.2, 11.35)   ... [23.65, 23.799999999999997) [23.799999999999997, 23.95) [23.95, 24.1)   [24.1, 24.25)   [24.25, 24.4)   [24.4, 24.549999999999997)  [24.549999999999997, 24.7)  [24.7, 24.85)   [24.85, 25.0)   [25.0, inf)
cos(theta)                                                                                  
[-inf, -1.0)    0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
[-1.0, -0.9)    0.0 1.0 1.0 0.0 0.0 2.0 0.0 2.0 0.0 1.0 ... 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
[-0.9, -0.8)    0.0 0.0 3.0 3.0 0.0 0.0 0.0 0.0 1.0 1.0 ... 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 0.0
[-0.8, -0.7)    0.0 0.0 1.0 2.0 0.0 1.0 1.0 2.0 1.0 1.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
[-0.7, -0.6)    0.0 0.0 1.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 ... 1.0 1.0 0.0 1.0 1.0 0.0 0.0 1.0 0.0 0.0
[-0.6, -0.5)    0.0 1.0 1.0 1.0 0.0 0.0 2.0 1.0 0.0 3.0 ... 0.0 1.0 0.0 1.0 1.0 0.0 1.0 0.0 0.0 0.0
[-0.5, -0.3999999999999999) 0.0 0.0 2.0 0.0 1.0 1.0 3.0 2.0 3.0 1.0 ... 3.0 0.0 0.0 0.0 0.0 2.0 0.0 1.0 1.0 0.0

从这里可以使用 pandas 的标准方法!

(使用 loc[] 和 iloc[] 等切片技术:https://www.youtube.com/watch?v=tcRGa2soc-c

【讨论】:

  • 在我有机会解释之前你就已经猜到了。 TH*.pandas() 函数的文档记录不足,但是一旦它采用 Pandas 形式,网上就有很多关于使用 Pandas DataFrames 的信息。这种想法是 DataFrames 不能很好地拟合粒子物理事件数据,因为可变数量的粒子不像表格那样是直线的。但是,聚合数据(直方图)确实非常适合 Pandas 的数据模型。由于 Pandas 具有区间索引类型,因此这是表示直方图的自然方式。
  • 它甚至可以很好地合并具有不同分箱的直方图,尽管它假设丢失的分箱应该用 NaN 填充,而不是 0(您可以用 fillna 填充)。您可以使用 Pandas 的重采样重新组合,但您必须明确告诉它您希望聚合函数为 sum。问题是直方图有一个自然的聚合函数 sum(其身份为 0),但 Pandas 不知道默认为这个。 (可以理解:它比这更笼统。)请注意,错误列是“方差”,因此它们像“计数”一样添加。
  • 感谢您的宝贵建议!还有一个问题:现在我的索引(以及coloum)的类型是IntervalIndex(元组系列?)。这不是 plt.plot 支持的格式!您将如何继续绘制 TH2D?
  • @JimPivarski 我使用 plt.pcloromesh() 尝试了此处建议的方法 (github.com/pandas-dev/pandas/issues/33560),但 IntervallIndex 索引和列的第一个和最后一个值都是 +-inf。我该如何处理?显然,通过切片 [1:] 和 [:-1] 来减小 IntervallIndex 会导致与 C 矩阵的维度(即计数)不匹配。一种策略可能是将 +inf 值设置为 + 同一索引的 .right 值之间的距离。我会尝试实现这一点,但你能建议我你的方法吗?谢谢!
  • 您可以通过edges[1:-1] 对边缘进行切片,并通过bins[1:-1, 1:-1] 对2d bin 进行切片。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-01
  • 2021-12-30
  • 2021-04-24
相关资源
最近更新 更多