警察局的傻瓜()用于具有多索引列的数据帧

2024-04-25 22:03:18 发布

您现在位置:Python中文网/ 问答频道 /正文

使用^{},可以为分类数据创建一个热编码的伪变量。例如:

import pandas as pd
df = pd.DataFrame({'A': ['a', 'b', 'a'], 
                   'B': ['b', 'a', 'c']})
print(pd.get_dummies(df))

#    A_a  A_b  B_a  B_b  B_c
# 0    1    0    0    1    0
# 1    0    1    1    0    0
# 2    1    0    0    0    1

到目前为止,还不错。但是如何将get_dummies()与多索引列结合使用呢?默认行为不太实际:多索引元组被转换成字符串,并且应用与简单索引列相同的后缀机制。在

^{pr2}$

不过,我想得到的是,这些假人创建了一个新的列级别:

ret = pd.get_dummies(df, ???)
print(ret)
print(type(ret.columns[0]))

#    i    ii
#    A     B
#    a  b  a  b  c
# 0  1  0  0  1  0
# 1  0  1  1  0  0
# 2  1  0  0  0  1
#
# tuple
#

# Note that the ret would be equivalent to the following:
#   ('i','A','a') ('i','A','b') ('ii','B','a') ('ii','B','b') ('ii','B','c')
# 0            1             0              0              1              0
# 1            0             1              1              0              0
# 2            1             0              0              0              1

如何实现这一目标?在

更新:我在get_dummies:https://github.com/pandas-dev/pandas/issues/26560中提出了一个特性请求,以更好地支持多索引数据帧


Tags: the数据importdataframepandas编码dfget
2条回答

我也有类似的需求,但在一个更复杂的数据帧中,用多个索引作为行索引,而数字列不能转换为虚拟的。因此,我的案例需要扫描所有列,扩展到仅虚拟dtype='object'的列,并构建一个新的列索引,将列名称与伪变量和伪变量本身的值连接起来。这是因为我不想添加新的列索引级别。在

这是密码 首先用我需要的格式构建一个数据帧 在

import pandas as pd
import numpy as np

df_size = 3
objects = ['obj1','obj2']
attributes = ['a1','a2','a3']
cols = pd.MultiIndex.from_product([objects, attributes], names=['objects', 'attributes'])
lab1 = ['car','truck','van']
lab2 = ['bay','zoe','ros','lol']
time = np.arange(df_size)
node = ['n1','n2']
idx = pd.MultiIndex.from_product([time, node], names=['time', 'node'])
df = pd.DataFrame(np.random.randint(10,size=(len(idx),len(cols))),columns=cols,index=idx)
c1 = map(lambda i:lab1[i],np.random.randint(len(lab1),size=len(idx)))
c2 = map(lambda i:lab2[i],np.random.randint(len(lab2),size=len(idx)))
df[('obj1','a3')]=list(c1)
df[('obj2','a2')]=list(c2)
print(df)
^{pr2}$

下面是只显示对象列的代码

^{3}$
objects    obj1                           obj2                               
attributes   a1 a2 a3_car a3_truck a3_van   a1 a2_bay a2_lol a2_ros a2_zoe a3
time node                                                                    
0    n1       6  5      0        1      0    3      0      0      1      0  3
     n2       5  6      1        0      0    9      0      1      0      0  7
1    n1       0  8      0        1      0    7      0      0      0      1  8
     n2       4  3      0        1      0    8      1      0      0      0  3
2    n1       5  8      0        0      1    0      1      0      0      0  0
     n2       4  8      1        0      0    5      0      1      0      0  4

它可以很容易地更改以响应原始用例,向列multi-index添加一行。在

df = pd.DataFrame({('i','A'): ['a', 'b', 'a'], 
                   ('ii','B'): ['b', 'a', 'c']})
print(df)
i ii
   A  B
0  a  b
1  b  a
2  a  c
df.columns = pd.MultiIndex.from_tuples([t+('',) for t in df.columns])
for t in [df.columns[i] for i,dt in enumerate(df.dtypes) if dt=='object']:
    dummy_block = pd.get_dummies( df[t] )
    dummy_block.columns = pd.MultiIndex.from_product([[t[0]],[t[1]],[c for c in dummy_block.columns]],
                                                     names=df.columns.names)
    df = pd.concat([df.drop(t,axis=1),dummy_block],axis=1).sort_index(axis=1)
print(df)
^{8}$

请注意,如果有数字列,它仍然有效-它只是在列索引中向它们添加一个空的额外级别。在

您可以分析列名并重命名它们:

import ast
def parse_dummy(x):
    parts = x.split('_')
    return ast.literal_eval(parts[0]) + (parts[1],)

ret.columns = pd.Series(ret.columns).apply(parse_dummy)
#   (i, A, a)  (i, A, b)  (ii, B, a)  (ii, B, b)  (ii, B, c)
#0          1          0           0           1           0
#1          0          1           1           0           0
#2          1          0           0           0           1

请注意,此DataFrame与具有三级多索引列名的DataFrame不同。在

相关问题 更多 >

    热门问题