Python Pandas - 发布 concat 多索引数据帧

Posted

技术标签:

【中文标题】Python Pandas - 发布 concat 多索引数据帧【英文标题】:Python Pandas - Issue concat multi-indexed Dataframes 【发布时间】:2017-06-30 01:55:58 【问题描述】:

我正在尝试合并两个 MultiIndex 的数据框。我的代码如下。正如您在输出中看到的那样,问题是重复“DATE”索引,而我希望所有值(OPEN_INT,PX_LAST)都在同一个日期索引上......有什么想法吗?我尝试了 append 和 concat,但都给出了相似的结果。

      if df.empty:
            df = bbg_historicaldata(t, f, startDate, endDate)
            print(df)            
            datesArray = list(df.index)
            tArray = [t for i in range(len(datesArray))]
            arrays = [tArray, datesArray]
            tuples = list(zip(*arrays))
            index = pd.MultiIndex.from_tuples(tuples, names=['TICKER', 'DATE'])                    
            df = pd.DataFrame(f : df[f].values, index=index)
    else:
        temp = bbg_historicaldata(t,f,startDate,endDate)
            print(temp)
            datesArray = list(temp.index)
            tArray = [t for i in range(len(datesArray))]
            arrays = [tArray, datesArray]
            tuples = list(zip(*arrays))
            index = pd.MultiIndex.from_tuples(tuples, names=['TICKER', 'DATE'])


            temp = pd.DataFrame(f : temp[f].values, index=index)

            #df = df.append(temp, ignore_index = True)
            df = pd.concat([df, temp], axis = 1).sortlevel()

基本上不想要 NaN!

                        PX_LAST   OPEN_INT  PX_LAST  OPEN_INT  PX_LAST  \
TICKER      DATE                                                         
EDH8 COMDTY 2017-02-01   98.365  1008044.0      NaN       NaN      NaN   
            2017-02-02   98.370  1009994.0      NaN       NaN      NaN   
            2017-02-03   98.360  1019181.0      NaN       NaN      NaN   
            2017-02-06   98.405  1023863.0      NaN       NaN      NaN   
            2017-02-07   98.410  1024609.0      NaN       NaN      NaN   
            2017-02-08   98.435  1046258.0      NaN       NaN      NaN   
            2017-02-09   98.395  1050291.0      NaN       NaN      NaN   
EDM8 COMDTY 2017-02-01      NaN        NaN   98.245  726739.0      NaN   
            2017-02-02      NaN        NaN   98.250  715081.0      NaN   
            2017-02-03      NaN        NaN   98.235  723936.0      NaN   
            2017-02-06      NaN        NaN   98.285  729324.0      NaN   
            2017-02-07      NaN        NaN   98.295  728673.0      NaN   
            2017-02-08      NaN        NaN   98.325  728520.0      NaN   
            2017-02-09      NaN        NaN   98.280  741840.0      NaN   
EDU8 COMDTY 2017-02-01      NaN        NaN      NaN       NaN   98.130   
            2017-02-02      NaN        NaN      NaN       NaN   98.135   
            2017-02-03      NaN        NaN      NaN       NaN   98.120   
            2017-02-06      NaN        NaN      NaN       NaN   98.180   
            2017-02-07      NaN        NaN      NaN       NaN   98.190   
            2017-02-08      NaN        NaN      NaN       NaN   98.225   
            2017-02-09      NaN        NaN      NaN       NaN   98.175  

编辑:做 Axis = 0,给出以下内容:。我希望它折叠重复的日期(即,每个日期索引都有唯一的值,没有重复的日期或 NaN)

                         OPEN_INT  PX_LAST
TICKER      DATE                          
EDH8 COMDTY 2017-02-01        NaN   98.365
            2017-02-01  1008044.0      NaN
            2017-02-02        NaN   98.370
            2017-02-02  1009994.0      NaN
            2017-02-03        NaN   98.360
            2017-02-03  1019181.0      NaN
            2017-02-06        NaN   98.405
            2017-02-06  1023863.0      NaN
            2017-02-07        NaN   98.410
            2017-02-07  1024609.0      NaN
            2017-02-08        NaN   98.435
            2017-02-08  1046258.0      NaN
            2017-02-09        NaN   98.395
            2017-02-09  1050291.0      NaN
EDM8 COMDTY 2017-02-01        NaN   98.245
            2017-02-01   726739.0      NaN
            2017-02-02        NaN   98.250
            2017-02-02   715081.0      NaN
            2017-02-03        NaN   98.235
            2017-02-03   723936.0      NaN
            2017-02-06        NaN   98.285
            2017-02-06   729324.0      NaN
            2017-02-07        NaN   98.295
            2017-02-07   728673.0      NaN
            2017-02-08        NaN   98.325
            2017-02-08   728520.0      NaN
            2017-02-09        NaN   98.280
            2017-02-09   741840.0      NaN

这是打印的输入数据。我在上面添加了 print(df) 和 print(temp) 。它们都是以 DATE 为索引的数据框。 TICKER 索引来自循环“for f in fields:”中的变量“f”

            PX_LAST
DATE               
2017-02-01   98.365
2017-02-02   98.370
2017-02-03   98.360
2017-02-06   98.405
2017-02-07   98.410
2017-02-08   98.435
2017-02-09   98.395
             OPEN_INT
DATE                 
2017-02-01  1008044.0
2017-02-02  1009994.0
2017-02-03  1019181.0
2017-02-06  1023863.0
2017-02-07  1024609.0
2017-02-08  1046258.0
2017-02-09  1050291.0
            PX_LAST
DATE               
2017-02-01   98.245
2017-02-02   98.250
2017-02-03   98.235
2017-02-06   98.285
2017-02-07   98.295
2017-02-08   98.325
2017-02-09   98.280
            OPEN_INT
DATE                
2017-02-01  726739.0
2017-02-02  715081.0
2017-02-03  723936.0
2017-02-06  729324.0
2017-02-07  728673.0
2017-02-08  728520.0
2017-02-09  741840.0
            PX_LAST
DATE               
2017-02-01   98.130
2017-02-02   98.135
2017-02-03   98.120
2017-02-06   98.180
2017-02-07   98.190
2017-02-08   98.225
2017-02-09   98.175
            OPEN_INT
DATE                
2017-02-01  584448.0
2017-02-02  574246.0
2017-02-03  581897.0
2017-02-06  585169.0
2017-02-07  590248.0
2017-02-08  598478.0
2017-02-09  595884.0

【问题讨论】:

TICKER 索引值不同。您要忽略/删除该索引级别吗?期望的结果是什么? 所以基本上我希望有一个多索引数据框。第一个索引是 TICKER。下一个索引是日期。然后是 PX_LAST 和 OPEN_INT 列。 对于每个代码,都会有时间序列数据,但所有代码将共享相同的列。 不只是显示输出,如果你显示你开始的起点会更容易,这样人们就可以进行实验。我怀疑你让这件事变得比需要的困难得多。 确定 - 一秒。我将添加编辑。 【参考方案1】:

您的逻辑有点难以理解(例如,很难理解为什么有时您会从数据调用中获得不同的列)。但是,AFAICT,实际上您只想在具有相同股票代码的所有帧中执行join(如果您将索引设置为 TICKER,DATE)或 merge,如果 TICKER 和 DATE 是列,然后连接结果那些。它试图在一个导致问题的步骤中同时完成它们。

或者,我们可以将整个内容连接起来,然后进行旋转,这就是我将在这里做的,因为它更容易显示。

(顺便说一句,在循环中重复连接可能会导致性能问题,因为每次都需要复制大量数据,通常应该避免——首先构建一个你想要连接的集合,然后应用它。)


假设您的每个框架开始如下所示(列可能不同):

In [532]: df
Out[532]: 
            PX_LAST
DATE               
2017-02-01   98.365
2017-02-02   98.370
2017-02-03   98.360
2017-02-06   98.405
2017-02-07   98.410
2017-02-08   98.435
2017-02-09   98.395

那么我只需将代码添加到框架并重置索引,而不是您现在正在做的事情:

In [549]: df = df.assign(TICKER=t).reset_index()   #TICKER variable = t
Out[549]: 
         DATE  PX_LAST       TICKER
0  2017-02-01   98.365  EDH8 COMDTY
1  2017-02-02   98.370  EDH8 COMDTY
2  2017-02-03   98.360  EDH8 COMDTY
3  2017-02-06   98.405  EDH8 COMDTY
4  2017-02-07   98.410  EDH8 COMDTY
5  2017-02-08   98.435  EDH8 COMDTY
6  2017-02-09   98.395  EDH8 COMDTY

为了让连接对内存更友好,让我们把它融化:

In [579]: pd.melt(df, id_vars=["TICKER", "DATE"])
Out[579]: 
        TICKER        DATE variable   value
0  EDH8 COMDTY  2017-02-01  PX_LAST  98.365
1  EDH8 COMDTY  2017-02-02  PX_LAST  98.370
2  EDH8 COMDTY  2017-02-03  PX_LAST  98.360
3  EDH8 COMDTY  2017-02-06  PX_LAST  98.405
4  EDH8 COMDTY  2017-02-07  PX_LAST  98.410
5  EDH8 COMDTY  2017-02-08  PX_LAST  98.435
6  EDH8 COMDTY  2017-02-09  PX_LAST  98.395

并将其附加到列表dfs。现在部分帧将很好地组合,因为它们都有相同的列,我们可以旋转以获得我们想要的输出:

In [589]: pd.concat(dfs).pivot_table(index=["TICKER", "DATE"], columns="variable", values="value")
Out[589]: 
variable                 OPEN_INT  PX_LAST
TICKER      DATE                          
EDH8 COMDTY 2017-02-01  1008044.0   98.365
            2017-02-02  1009994.0   98.370
            2017-02-03  1019181.0   98.360
            2017-02-06  1023863.0   98.405
[...]

这避免了所有那些中间的 NaN。由于即使您不熔化,串联+枢轴方法也可以工作,所以起初我没有进行熔化,但再想想,即使它有效,因为中间内存需求可能会增长到禁止。

【讨论】:

你是个传奇,感谢帝斯曼!出于好奇,为什么拥有大量列会改变您处理此问题的方式? @keynesiancross:您拥有的列(或行,就此而言)越多,您的中间预透视数据框就越多只是 NaN。这意味着您可以在内存中拥有一个巨大的中间帧,即使最终版本会小很多倍。事实上,我实际上会改变我的推荐顺序,以免导致其他人走上这条路.. 实际上-现在我正在考虑它,如果您在循环之外执行 concat(dfs).pivot_table() ,您最终会得到所有这些 NaN 吗?即,您将构建一个只有日期并完全归档在列数据中的 df 列表。 NaN 只是我原始代码的副产品 @keynesiancross:是的,它们出现了,主要是因为 concat 仍然尝试将只有 OPEN_INT 的子帧与只有 PX_LAST 的子帧结合起来。

以上是关于Python Pandas - 发布 concat 多索引数据帧的主要内容,如果未能解决你的问题,请参考以下文章

Python,在 Pandas DataFrame 的“group concat”中使用“order by”

Python Pandas Concat "WHERE" 满足条件

python数据表的合并(python pandas join() merge()和concat()的用法)

python数据表的合并(python pandas join() merge()和concat()的用法)

python--pandas合并与连接

Python数据分析库pandas ------ mergeconcatenation pd.concat合并与拼接