我有两个具有相同列和索引的数据帧。我想将它们组合成具有分层索引的第三个数据帧,维护当前索引并添加一个标识每个DataFrame来源的秒。这就是我试过的:
df_a = pd.DataFrame(randn(3, 2), columns=["x", "y"], index=range(3))
df_b = pd.DataFrame(randn(3, 2), columns=["x", "y"], index=range(3))
tuples = list(itertools.product(["a", "b"], range(3)))
df = pd.DataFrame(columns=["x", "y"], index=pd.MultiIndex.from_tuples(tuples))
df.loc["a"] = df_a
df.loc["b"] = df_b
然而,df
仍然充满NaNs
,当我预计它会填充df_a
和df_b
的值时。 工作:
df.loc["a"] = np.array(df_a)
但似乎既迂回又错误。
我对层次指数不了解什么?什么是实现我的目标的最佳方式?
答案 0 :(得分:2)
In [1]: df_a = pd.DataFrame(randn(3, 2), columns=["x", "y"], index=range(3))
In [2]: df_b = pd.DataFrame(randn(3, 2), columns=["x", "y"], index=range(3))
In [3]: pd.concat([df_a, df_b], keys=['a', 'b'])
Out[3]:
x y
a 0 0.913812 -1.719241
1 0.544462 0.845426
2 -0.269518 -1.549679
b 0 0.534311 1.693824
1 0.119147 -0.171002
2 0.595658 0.588252
答案 1 :(得分:1)
实现此目的而不是填充数据框df
的另一种方法是将多索引添加到原始数组(df_a
和df_b
) ,然后连接它们(见下文)。
df
未填充的原因是因为pandas根据索引进行数据对齐。在为df.ix["a"]
分配另一个数据帧时,它会填充索引匹配的值。为了说明这一点:
>>> df = pd.DataFrame(randn(3, 2), columns=["x", "y"], index=range(3))
>>> df2 = pd.DataFrame(zeros((1, 2)), columns=["x", "y"], index=range(2,3))
>>> df
x y
0 -0.995116 0.132438
1 -0.023010 -0.211612
2 -0.053206 0.427369
>>> df2
x y
2 0 0
>>> df.ix[:] = df2
>>> df
x y
0 NaN NaN
1 NaN NaN
2 0 0
当分配numpy数组(或列表,..)时,没有要匹配的索引,所以它只填充数据帧(在这种情况下也是广播):
>>> df.ix[:] = df2.values
>>> df
x y
0 0 0
1 0 0
2 0 0
所以,在您的情况下,当您尝试将df_a
分配给df.ix['a']
时,索引不匹配(MultiIndex与普通索引),并且没有任何内容被分配(或更确切地说:填充NaN的)。但是,当您第一次将df_a
转换为具有相同的MultiIndex时,它确实有效:
>>> df_a = pd.DataFrame(randn(3, 2), columns=["x", "y"], index=range(3))
>>> df_b = pd.DataFrame(randn(3, 2), columns=["x", "y"], index=range(3))
>>>
>>> tuples = list(itertools.product(["a", "b"], range(3)))
>>> df = pd.DataFrame(columns=["x", "y"], index=pd.MultiIndex.from_tuples(tuples))
>>>
>>> df_a.index = pd.MultiIndex.from_tuples([tuple(('a', i)) for i in df_a.index])
>>>
>>> df.ix["a"] = df_a
>>> df
x y
a 0 1.533881 1.276075
1 -0.5143746 -0.3400633
2 -1.071509 1.831282
b 0 NaN NaN
1 NaN NaN
2 NaN NaN
或者如上所述,当使用numpy数组时(.values
属性将数据作为numpy数组返回),它也可以工作:
>>> df.ix["b"] = df_b.values
>>> df
x y
a 0 1.533881 1.276075
1 -0.5143746 -0.3400633
2 -1.071509 1.831282
b 0 0.06535034 -0.6276186
1 0.008100781 0.9512881
2 0.08688541 -0.7101486
但我认为,实现此的另一种方式,而不是填充数据框df
,是将多索引添加到原始数组,然后连接它们< / EM>:
要将其转换为MultiIndex,您可以这样做:
>>> df_a['df'] = 'a'
>>> df_b['df'] = 'b'
>>>
>>> df_a = df_a.set_index('df', append=True)
>>> df_b = df_b.set_index('df', append=True)
或者像这样:
>>> df_a.index = pd.MultiIndex.from_tuples([tuple(('a', i)) for i in df_a.index])
>>> df_b.index = pd.MultiIndex.from_tuples([tuple(('b', i)) for i in df_b.index])
然后你可以连接它们:
>>> df = pd.concat([df_a, df_b])
>>> df
x y
df
0 a -0.225156 -0.846229
1 a 1.566139 0.892763
2 a -1.291920 -0.517408
0 b 1.464853 0.792709
1 b -1.307375 -0.360373
2 b 0.467406 1.249325
>>>
>>> df.swaplevel(0,1)
x y
df
a 0 -0.225156 -0.846229
1 1.566139 0.892763
2 -1.291920 -0.517408
b 0 1.464853 0.792709
1 -1.307375 -0.360373
2 0.467406 1.249325