pandas:在 MultiIndex DataFrame 上复制/广播单索引 DataFrame:操作方法和内存效率

Posted

技术标签:

【中文标题】pandas:在 MultiIndex DataFrame 上复制/广播单索引 DataFrame:操作方法和内存效率【英文标题】:pandas: Replicate / Broadcast single indexed DataFrame on MultiIndex DataFrame: HowTo and Memory Efficiency 【发布时间】:2018-07-26 05:43:15 【问题描述】:

问题

股票交易的机器学习数据准备。我在大型 DataFrame 上有 3-dim MultiIndex(可能是n=800000 x f=20)。一个指数维度是date 和大约dt=1000 水平,其他识别m=800 不同的股票(每个有20 个特征,每个股票单独)。所以对于每个日期,都有 800 x 20 个不同的值。

现在我有 dt=1000 x g=30全球时间序列(如 DJIA、货币汇率等),因此每个日期的 30 个值对于每只股票相同 .这是一个只有日期作为索引的单一索引 DataFrame。

问题 1

如何合并这两个数据集,以便将 30 个系列广播到每只股票上,最终得到形状 (800000 x 50)

问题 2

有没有办法不是通过复制后面 30 列的数据,而是通过查看原始数据来节省内存?根据我提到的数字,对于 float64 精度,我仍将保持在 ~ 300 MB,这仍然可以。但我很好奇。

示例

这是我所拥有的f=2g=1m=4dt=3 的最小示例:

import pandas as pd

data = 
    'x': [5,6,7,3,4,5,1,1,0,12,15,14],
    'y': [4,6,5,5,4,3,2,0,1,13,14,13]


dates = [pd.to_datetime('2018-01-01'), pd.to_datetime('2018-01-02'), pd.to_datetime('2018-01-03')]

index = pd.MultiIndex.from_arrays([
    ['alpha'] * 6 + ['beta'] * 6,
    ['A'] * 3 + ['B'] * 3 + ['C'] * 3 + ['D'] * 3,
    dates * 4,
])
df1 = pd.DataFrame(data, index=index)

df1.index.names = ['level', 'name', 'date']


df2 = pd.DataFrame([123,124,125], index=dates, columns=['z'])
df2.index.name = "date"

print (df1)
print (df2)
-------------------------------
                        x   y
level name date              
alpha A    2018-01-01   5   4
           2018-01-02   6   6
           2018-01-03   7   5
      B    2018-01-01   3   5
           2018-01-02   4   4
           2018-01-03   5   3
beta  C    2018-01-01   1   2
           2018-01-02   1   0
           2018-01-03   0   1
      D    2018-01-01  12  13
           2018-01-02  15  14
           2018-01-03  14  13

              z
date           
2018-01-01  123
2018-01-02  124
2018-01-03  125

还有我喜欢的:

                        x   y     z
level name date              
alpha A    2018-01-01   5   4   123
           2018-01-02   6   6   124
           2018-01-03   7   5   125
      B    2018-01-01   3   5   123
           2018-01-02   4   4   124
           2018-01-03   5   3   125
beta  C    2018-01-01   1   2   123
           2018-01-02   1   0   124
           2018-01-03   0   1   125
      D    2018-01-01  12  13   123
           2018-01-02  15  14   124
           2018-01-03  14  13   125

【问题讨论】:

【参考方案1】:

我认为需要 joinDataFrames 中为相同的索引名称 date 对齐:

df = df1.join(df2)
print (df)
                        x   y    z
level name date                   
alpha A    2018-01-01   5   4  123
           2018-01-02   6   6  124
           2018-01-03   7   5  125
      B    2018-01-01   3   5  123
           2018-01-02   4   4  124
           2018-01-03   5   3  125
beta  C    2018-01-01   1   2  123
           2018-01-02   1   0  124
           2018-01-03   0   1  125
      D    2018-01-01  12  13  123
           2018-01-02  15  14  124
           2018-01-03  14  13  125

【讨论】:

又好又简单! df 将使用多少内存? df1+df2df1+m*df2? 我正在考虑您的第二个问题和难题。我不知道:( @ascripter 这工作得非常巧妙,因为在您的示例数据中,两个数据帧中的索引都有一个名为date 的级别,所以join 知道要加入什么。确保您的真实数据中确实如此。 @ascripter 至于你的第二个问题,节省内存的唯一方法是一次以块的形式提供数据,并根据需要从第二个数据帧中提取数据。这并不简单。 @piRSquared - 我在考虑categoricals,但不确定是否可以在这里使用。

以上是关于pandas:在 MultiIndex DataFrame 上复制/广播单索引 DataFrame:操作方法和内存效率的主要内容,如果未能解决你的问题,请参考以下文章

合并 pandas MultiIndex 很慢

在 Pandas 中使用 .loc 和 MultiIndex

在 Pandas 中将两个 MultiIndex 级别合并为一个

pandas - 如何使用 MultiIndex 在 DataFrame 的深层检索最小值索引

pandas:将两个 DataFrame 与已排序的 MultiIndex 连接起来,使得结果具有已排序的 MultiIndex

Pandas:从 DataFrame 分配 MultiIndex 列