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