通过get_dummies和pivot_table在融体上加入后的一键编码

时间:2018-08-09 19:49:11

标签: python pandas

我有一些数据,希望在添加一些标签后进行一次编码。以下代码适用于玩具示例,并且是我在类似情况下采用的方法。但是,它无法缩放。例如,使用以下数据框:

import pandas as pd
import numpy as np

df = pd.DataFrame({'id' : [1, 2],
                   'C1' : ['X1', 'X2'],
                   'C2' : ['X2', np.NaN],
                   'C3' : ['X3', np.NaN],
                   'C4' : ['X4', 'X4']})

此时df由包含顺序无关紧要的字符串值的列组成。因此,立即pd.get_dummies(df, prefix = '', prefix_sep = '', columns = ['C1', 'C2', 'C3', 'C4']将输出带有两个C2列的单热编码数据帧,例如,这是不希望的。

条目(id)的长度可能有所不同(因此,np.NaN)。任何给定的id都不会包含重复的条目。但是,这些字符串值可能属于我希望为其添加标签的另一类。

label_list = pd.DataFrame({'strval': ['X1','X2','X3','X4'],
                           'label' : [np.NaN, 'red', 'blue', 'red']})

然后我融化df并加入字符串val以使标签位于适当的位置

dflong = pd.melt(df, id_vars = ['id'],
                 value_vars = ['C1', 'C2', 'C3', 'C4'],
                 value_name = 'strval')

dflab = dflong.merge(label_list, on = 'strval')

这有效,但是在我的真实数据集中,一百万行变成了2000万行。 get_dummies还在自己的行上分别对所有内容进行编码。接下来是pd.pivot_table,将其成形为适当的格式。

dflab_gd = pd.get_dummies(dflab.drop(columns = ['variable']),
                          columns = ['strval', 'label'],
                          prefix = '', prefix_sep = '')

现在,我想将此结果展平,以便每个id有一个条目。

dflab_gd_flt = dflab_gd.pivot_table(index = ['id'], aggfunc = 'any', 
fill_value = 0).astype(int)

我喜欢这种方法,因为当我希望通过更改aggfunc来计算适合同一标签的strval显示多少次时,我也可以将标签保留为计数。

那么我的问题是:这种方法的伸缩性根本不好。是否存在另一种分配标签并获得计算效率更高的单热编码数据帧(或针对strval和计数的单热编码)的方法?也许不涉及重塑融化的长期结果?将get_dummies应用于我的实际融化集后,我得到一个0/1数据帧,该数据帧为2000万行乘以30,000列。

1 个答案:

答案 0 :(得分:1)

您不需要进行一键编码。如果将“标签”和“ strval”放在同一列中,然后按组进行分组,那么您应该会得到所需的信息。

df_concat = pd.concat(
    (dflab.drop(columns=['label']).rename({'strval': 'val'}, axis=1), 
     dflab.drop(columns=['strval']).rename({'label': 'val'}, axis=1)), 
    axis=0)

# use .any() or .count() as you would set aggfunc='any' or 'count'
dfg = df_concat.groupby(['id', 'val']).count()

# pivot to go from long to wide dataframe
dfg.reset_index().pivot('id', 'val').fillna(0).astype(int)