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()的用法)