根据类别列表对变量进行Dummify

时间:2018-01-09 16:23:57

标签: python pandas

例如,我的数据框如下所示。

>>> df
  CATX CATY CATZ
0    A    G  AAA
1    B    H  BBB
2    C    I  AAA
3    B    J  CCC
4    A    G  BBB
5    B    H  DDD
6    D    K  EEE
7    E    L  FFF

我想根据列表中提供的值在df上添加新列。例如,对于CATZ,我有一个列表['AAA', 'BBB'],我需要考虑这个列表来指示obervation是1或0,例如

>>> df
  CATX CATY CATZ  AAA  BBB
0    A    G  AAA    1    0
1    B    H  BBB    0    1
2    A    I  AAA    1    0
3    B    J  CCC    0    0
4    A    H  BBB    0    1
5    B    H  DDD    0    0
6    D    K  EEE    0    0
7    E    L  FFF    0    0

这与pd.get_dummies略有不同,因为get_dummies会考虑整个数据框/列上的所有可能值(或k-1值)。目前,我正在做的是遍历列表并执行每行的申请。

for catz_item in catz_list:
    df[catz_item] = df.apply(lambda x: 1 if x.CATZ == catz_item else 0, axis=1)

除了迭代列表之外还有其他方法吗(因为这个循环有点慢)。为了使它更复杂,我也使用基于某个列表的CATX和CATY的组合来做到这一点,例如[[' A',' G'],[& #39; A',' H'],[' B'' H']]。

---编辑---

使用CATX / CATY

组合输出
>>> df
  CATX CATY CATZ  AAA  BBB  AG  AH  BH
0    A    G  AAA    1    0   1   0   0
1    B    H  BBB    0    1   0   0   1
2    C    I  AAA    1    0   0   0   0
3    B    J  CCC    0    0   0   0   0
4    A    G  BBB    0    1   1   0   0
5    B    H  DDD    0    0   0   0   1
6    D    K  EEE    0    0   0   0   0
7    E    L  FFF    0    0   0   0   0

我现在使用的代码如下所示

catxy_list = [['A', 'G'], ['A', 'H'], ['B', 'H']]   
for catxy_item in catxy_list:
    df[catxy_item[0] + catxy_item[1]] = df.apply(lambda x: 1 if x.CATX == catxy_item[0] and x.CATY == catxy_item[1] else 0, axis=1)

4 个答案:

答案 0 :(得分:3)

对于涉及CATZ的第一位,您可以使用where / mask + get_dummies -

v = df.CATZ.where(df.CATZ.isin(['AAA', 'BBB'])).str.get_dummies()

或者,

v = df.CATZ.mask(~df.CATZ.isin(['AAA', 'BBB'])).str.get_dummies()

接下来,对于您的“复杂查询”,最后使用numpy广播进行astype转换 -

# initial values to compare
i = np.array([['A', 'G'], ['A', 'H'], ['B', 'H']])
# perform broadcasted comparison with `i` and convert the result to OHEs
j = (df.iloc[:, :-1].values[:, None] == i).all(2).astype(int)

# load the result into a dataframe  with the appropriate column names 
j = pd.DataFrame(j, columns=list(map(''.join, i)))

“复杂查询”的另一个较慢但更节省内存的选项是循环遍历每个类别并找到OHE:

ohe = []
for x, y in [['A', 'G'], ['A', 'H'], ['B', 'H']]:
    # generate OHEs for each pair of elements per category
    s = df.CATX.eq(x) & df.CATY.eq(y)  # s = df[['CATX', 'CATY']].isin([x, y]).all(1)
    s.name = ''.join([x, y])
    ohe.append(s)

# concatenate the intermediate results
j = pd.concat(ohe, 1).astype(int)

最后,您可以使用dfvjconcat加载到新数据框中。

pd.concat([df, v, j], 1)

  CATX CATY CATZ  AAA  BBB  AG  AH  BH
0    A    G  AAA    1    0   1   0   0
1    B    H  BBB    0    1   0   0   1
2    C    I  AAA    1    0   0   0   0
3    B    J  CCC    0    0   0   0   0
4    A    G  BBB    0    1   1   0   0
5    B    H  DDD    0    0   0   0   1
6    D    K  EEE    0    0   0   0   0
7    E    L  FFF    0    0   0   0   0

答案 1 :(得分:2)

In [403]: df.join(df.CATZ.str.get_dummies())
Out[403]:
  CATX CATY CATZ  AAA  BBB  CCC  DDD  EEE  FFF
0    A    G  AAA    1    0    0    0    0    0
1    B    H  BBB    0    1    0    0    0    0
2    C    I  AAA    1    0    0    0    0    0
3    B    J  CCC    0    0    1    0    0    0
4    A    G  BBB    0    1    0    0    0    0
5    B    H  DDD    0    0    0    1    0    0
6    D    K  EEE    0    0    0    0    1    0
7    E    L  FFF    0    0    0    0    0    1

或:

In [410]: df.join(df.CATZ[df.CATZ.isin(['AAA','BBB'])].str.get_dummies(), how='left').fillna(0)
Out[410]:
  CATX CATY CATZ  AAA  BBB
0    A    G  AAA  1.0  0.0
1    B    H  BBB  0.0  1.0
2    C    I  AAA  1.0  0.0
3    B    J  CCC  0.0  0.0
4    A    G  BBB  0.0  1.0
5    B    H  DDD  0.0  0.0
6    D    K  EEE  0.0  0.0
7    E    L  FFF  0.0  0.0

答案 2 :(得分:2)

pd.crosstab(df.index,df.CATZ)[['AAA','BBB']]
Out[66]: 
CATZ   AAA  BBB
row_0          
0        1    0
1        0    1
2        1    0
3        0    0
4        0    1
5        0    0
6        0    0
7        0    0

pd.concat([df,pd.crosstab(df.index,df.CATZ)[['AAA','BBB']]],1)
Out[68]: 
      CATX CATY CATZ  AAA  BBB
row_0                         
0        A    G  AAA    1    0
1        B    H  BBB    0    1
2        C    I  AAA    1    0
3        B    J  CCC    0    0
4        A    G  BBB    0    1
5        B    H  DDD    0    0
6        D    K  EEE    0    0
7        E    L  FFF    0    0

答案 3 :(得分:1)

认为您需要两个np.where

df["AAA"] = np.where(df["CATZ"] == "AAA", 1, 0)
df["BBB"] = np.where(df["CATZ"] == "BBB", 1, 0)

当标签很多时,这可能会很慢!