使用分层列创建DataFrame

17

如何使用分层列创建一个DataFrame是最简单的方法?

我目前正在使用以下代码从名称->Series字典创建DataFrame

df = pd.DataFrame(data=serieses)

我想使用相同的列名,但在列上添加额外的层次结构。 目前,我希望额外的级别对于所有列都具有相同的值,比如 "Estimates"。

我尝试了以下代码,但似乎不起作用:

pd.DataFrame(data=serieses,columns=pd.MultiIndex.from_tuples([(x, "Estimates") for x in serieses.keys()]))

我得到的只是一个全部为NaN的DataFrame

例如,我大概想要的结果是:

l1               Estimates    
l2  one  two  one  two  one  two  one  two
r1   1    2    3    4    5    6    7    8
r2   1.1  2    3    4    5    6    71   8.2

其中l1和l2是MultiIndex的标签

4个回答

16

这似乎有效:

import pandas as pd

data = {'a': [1,2,3,4], 'b': [10,20,30,40],'c': [100,200,300,400]}

df = pd.concat({"Estimates": pd.DataFrame(data)}, axis=1, names=["l1", "l2"])

l1  Estimates         
l2          a   b    c
0           1  10  100
1           2  20  200
2           3  30  300
3           4  40  400

1
非常易读,我喜欢它。最终,Pandas 最好拥有更好的“级别”管理,比如一个简单的 df.add_level(axis=1) - Rutger Kassies

11

我知道这个问题已经很老了,但对于 pandas 的版本 0.19.1,可以使用直接字典初始化:

d = {('a','b'):[1,2,3,4], ('a','c'):[5,6,7,8]}
df = pd.DataFrame(d, index=['r1','r2','r3','r4'])
df.columns.names = ('l1','l2')
print df

l1  a   
l2  b  c
r1  1  5
r2  2  6
r3  3  7
r4  4  8

这还能用吗?我尝试了直接字典初始化,但列只是元组。 - zkytony
@zkytony,我刚刚用不太旧的1.2.0版本检查了一下,这个问题仍然存在,至少在我的机器上是这样。你尝试升级你的pandas安装了吗?P.S 最新的1.3.3也是同样的情况。 - DimG

2

我不确定,但我认为将字典用作您的DF的输入多重索引不太兼容。改用数组作为输入可以解决此问题。

尽管如此,我通常更喜欢使用字典作为输入,一种方法是在创建df之后设置列:

import pandas as pd

data = {'a': [1,2,3,4], 'b': [10,20,30,40],'c': [100,200,300,400]}
df = pd.DataFrame(np.array(data.values()).T, index=['r1','r2','r3','r4'])

tups = zip(*[['Estimates']*len(data),data.keys()])

df.columns = pd.MultiIndex.from_tuples(tups, names=['l1','l2'])

l1          Estimates         
l2          a   c    b
r1          1  10  100
r2          2  20  200
r3          3  30  300
r4          4  40  400

当将数组作为df的输入时:

data_arr = np.array([[1,2,3,4],[10,20,30,40],[100,200,300,400]])

tups = zip(*[['Estimates']*data_arr.shape[0],['a','b','c'])
df = pd.DataFrame(data_arr.T, index=['r1','r2','r3','r4'], columns=pd.MultiIndex.from_tuples(tups, names=['l1','l2']))

这将得到相同的结果。


在字典示例中,列的顺序是否会混乱?换句话说,当Pandas从字典中创建DataFrame时,它必须从字典中提取键/值,这将以任意顺序发生。我认为您假设up/list comprehension语句中的顺序相同。这似乎是长期不安全的。我相信,在DataFrame构建中设置columns关键字时,Pandas会尝试确保某种对齐方式。 - Alex Rothberg
很好,你确实想要避免那种情况。使用np.array(data.values()).Tdata.keys()应该没问题。 - Rutger Kassies
根据文档http://docs.python.org/2/library/stdtypes.html#dict.items,这个新提案似乎确实是安全的。 - Alex Rothberg
调用transpose有什么问题吗?例如,是否存在任何情况会导致dtypes混乱? - Alex Rothberg
你认为允许通过创建DataFrame的DataFrame来创建这个是否有意义呢?例如:pd.DataFrame({"估计值": pd.DataFrame(data)})? - Alex Rothberg

1
Rutger Kassies的解决方案在我的情况下起作用了,但是在“上级”列层次结构中我有多列。仅提供一个对我有效的示例,因为这是一种更普遍的情况。首先,我的数据如下所示:
> df
         (A, a)    (A, b)       (B, a)    (B, b) 
0         0.00     9.75         0.00       0.00
1         8.85     8.86         35.75      35.50
2         8.51     9.60         66.67      50.70
3         0.03     508.99       56.00      8.58

我希望它看起来像这样:

> df
                A                    B
           a        b            a          b
0         0.00     9.75         0.00       0.00
1         8.85     8.86         35.75      35.50
...

解答如下:

解决方案是:

tuples = df.transpose().index
new_columns = pd.MultiIndex.from_tuples(tuples, names=['Upper', 'Lower'])
df.columns = new_columns

这很反直觉,因为要创建列,我必须通过索引来完成。

你也可以这样做:new_columns = pd.MultiIndex.from_tuples(df.columns, names=['Upper', 'Lower']); df.columns = new_columns - Joan Marcè i Igual

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接