如何将我的pandas数据分组推广到3个以上的维度?

Tim*_*omb 10 python pandas

我正在使用优秀的pandas软件包来处理大量不同的气象诊断数据,而且当我将数据拼接在一起时,我很快就会耗尽尺寸.查看文档,可能是使用MultiIndex可以解决我的问题,但我不知道如何将其应用于我的情况 - 文档显示了使用随机数据和DataFrames 创建MultiIndex的示例,但没有预先存在的Series时间序列数据.

背景

我使用的基本数据结构包含两个主要字段:

  • metadata,这是一个字典,由描述数字的键值对组成
  • data,这是一个包含数字本身的pandas数据结构.

最小公分母是时间序列数据,因此基本结构有一个pandas Series对象作为data条目,该metadata字段描述了这些数字实际上是什么(例如,东太平洋10米风的矢量RMS误差,24小时预测来自实验Test1).

我正在考虑采用最低通用分母并将各种时间序列粘合在一起,以使结果更有用,并允许轻松组合.例如,我可能想要查看所有不同的提前期 - 我有一个过滤器例程,它将占用我的时间序列共享相同的元数据条目,除了提前期(例如实验,区域等)并返回一个新对象该metadata字段仅包含公共条目(Lead Time即已被删除),现在该data字段是一个大熊猫DataFrame,其中列标签由Lead Time值给出.我可以再次对此进行扩展,并说我想取得结果帧并将它们组合在一起,只有另一个不同的条目(例如Experiment)给我一只大熊猫Panel.对于我的条目,其中项索引由Experiment组成框架的元数据值给出,并且对象的新元数据不包含Lead TimeExperiment.

当我迭代这些复合对象时,我有一个iterseries例程,iterframes用于面板的框架和例程,当我删除一个维度时重建适当的元数据/数据配对(即,来自框架的系列,其中提前时间在列中变化将具有所有其父元数据的元数据加上Lead Time使用从列标签中获取的值恢复的字段.这非常有效.

问题

我已经用完维度(使用Panel最多3-D)并且我也无法dropna在Panel中对齐所有内容之后删除空列(这会在绘制汇总统计信息时导致一些错误).阅读有关使用具有更高维度数据的大熊猫已经阅读了有关MultiIndex它及其使用的内容.我已经尝试过文档中给出的示例,但是我仍然有点不清楚如何将它应用到我的情况中.任何方向都会有用.我希望能够:

  • Series基于我的数据组合成一个DataFrame沿任意数量维度的多索引(这将是很棒的 - 它将消除一个调用来创建系列中的帧,然后另一个调用从帧创建面板)
  • 迭代生成的多索引DataFrame,删除单个维度,以便重置组件元数据.

编辑 - 添加代码示例

下面的Wes McKinney的答案几乎就是我所需要的 - 问题在于我开始将元素组合在一起时,我必须使用系列支持的存储对象的初始翻译,以及我的DataFrame支持的对象.Data-Frame支持的类具有以下方法,该方法接收基于系列的对象的列表以及将在列之间变化的元数据字段.

@classmethod
def from_list(cls, results_list, column_key):
    """
    Populate object from a list of results that all share the metadata except
    for the field `column_key`.

    """
    # Need two copies of the input results - one for building the object
    # data and one for building the object metadata
    for_data, for_metadata = itertools.tee(results_list)

    self             = cls()
    self.column_key  = column_key
    self.metadata    = next(for_metadata).metadata.copy()
    if column_key in self.metadata:
        del self.metadata[column_key]
    self.data = pandas.DataFrame(dict(((transform(r[column_key]), r.data)
                                        for r in for_data)))
    return self
Run Code Online (Sandbox Code Playgroud)

一旦我有了这个例程给出的框架,我就可以轻松应用下面建议的各种操作 - 特别是实用程序可以names在我调用时使用该字段concat- 这样就无需在内部存储列密钥的名称,因为它已存储在MultiIndex中作为索引维度的名称.

我希望能够实现下面的解决方案,只需要列出匹配的系列支持的类列表和键列表,然后按顺序进行分组.但是,我不知道列将提前代表什么,所以:

  • 将系列数据存储在1-D DataFrame中对我来说真的没有意义
  • 我没有看到如何设置索引的名称和初始Series - > Frame分组中的列

Wes*_*ney 10

我可能会建议使用pandas.concat它的keys参数将Series DataFrames粘合在一起,在列中创建一个MultiIndex:

In [20]: data
Out[20]: 
{'a': 2012-04-16    0
2012-04-17    1
2012-04-18    2
2012-04-19    3
2012-04-20    4
2012-04-21    5
2012-04-22    6
2012-04-23    7
2012-04-24    8
2012-04-25    9
Freq: D,
 'b': 2012-04-16    0
2012-04-17    1
2012-04-18    2
2012-04-19    3
2012-04-20    4
2012-04-21    5
2012-04-22    6
2012-04-23    7
2012-04-24    8
2012-04-25    9
Freq: D,
 'c': 2012-04-16    0
2012-04-17    1
2012-04-18    2
2012-04-19    3
2012-04-20    4
2012-04-21    5
2012-04-22    6
2012-04-23    7
2012-04-24    8
2012-04-25    9
Freq: D}

In [21]: df = pd.concat(data, axis=1, keys=['a', 'b', 'c'])

In [22]: df
Out[22]: 
            a  b  c
2012-04-16  0  0  0
2012-04-17  1  1  1
2012-04-18  2  2  2
2012-04-19  3  3  3
2012-04-20  4  4  4
2012-04-21  5  5  5
2012-04-22  6  6  6
2012-04-23  7  7  7
2012-04-24  8  8  8
2012-04-25  9  9  9

In [23]: df2 = pd.concat([df, df], axis=1, keys=['group1', 'group2'])

In [24]: df2
Out[24]: 
            group1        group2      
                 a  b  c       a  b  c
2012-04-16       0  0  0       0  0  0
2012-04-17       1  1  1       1  1  1
2012-04-18       2  2  2       2  2  2
2012-04-19       3  3  3       3  3  3
2012-04-20       4  4  4       4  4  4
2012-04-21       5  5  5       5  5  5
2012-04-22       6  6  6       6  6  6
2012-04-23       7  7  7       7  7  7
2012-04-24       8  8  8       8  8  8
2012-04-25       9  9  9       9  9  9
Run Code Online (Sandbox Code Playgroud)

你有:

In [25]: df2['group2']
Out[25]: 
            a  b  c
2012-04-16  0  0  0
2012-04-17  1  1  1
2012-04-18  2  2  2
2012-04-19  3  3  3
2012-04-20  4  4  4
2012-04-21  5  5  5
2012-04-22  6  6  6
2012-04-23  7  7  7
2012-04-24  8  8  8
2012-04-25  9  9  9
Run Code Online (Sandbox Code Playgroud)

甚至

In [27]: df2.xs('b', axis=1, level=1)
Out[27]: 
            group1  group2
2012-04-16       0       0
2012-04-17       1       1
2012-04-18       2       2
2012-04-19       3       3
2012-04-20       4       4
2012-04-21       5       5
2012-04-22       6       6
2012-04-23       7       7
2012-04-24       8       8
2012-04-25       9       9
Run Code Online (Sandbox Code Playgroud)

你可以有任意多个级别:

In [29]: pd.concat([df2, df2], axis=1, keys=['tier1', 'tier2'])
Out[29]: 
             tier1                       tier2                    
            group1        group2        group1        group2      
                 a  b  c       a  b  c       a  b  c       a  b  c
2012-04-16       0  0  0       0  0  0       0  0  0       0  0  0
2012-04-17       1  1  1       1  1  1       1  1  1       1  1  1
2012-04-18       2  2  2       2  2  2       2  2  2       2  2  2
2012-04-19       3  3  3       3  3  3       3  3  3       3  3  3
2012-04-20       4  4  4       4  4  4       4  4  4       4  4  4
2012-04-21       5  5  5       5  5  5       5  5  5       5  5  5
2012-04-22       6  6  6       6  6  6       6  6  6       6  6  6
2012-04-23       7  7  7       7  7  7       7  7  7       7  7  7
2012-04-24       8  8  8       8  8  8       8  8  8       8  8  8
2012-04-25       9  9  9       9  9  9       9  9  9       9  9  9
Run Code Online (Sandbox Code Playgroud)