44_Pandas将分类变量转换为虚拟变量(get_dummies)

44_Pandas将分类变量转换为虚拟变量(get_dummies)

要将分类变量(分类数据、定性数据)转换为 pandas 中的虚拟变量,请使用 pandas.get_dummies() 函数。

按字符串分类的性别等数据可以转换为男性为0,女性为1,多类特征可以转换为one-hot表达式。通常作为机器学习的预处理执行。

这里,将描述以下内容。

  • pandas.get_dummies()的基本用法
  • 排除第一类:drop_first
  • 缺失值NaN虚拟化:dummy_na
  • 指定pandas.DataFrame的虚拟变量的列名:prefix,prefix_sep
  • 在pandas.DataFrame 中指定列的虚拟数字/布尔列:columns
  • 任意数字化每个类别(级别):map()方法

以下数据用作示例。

import pandas as pd
import numpy as np

df = pd.read_csv('./data/44/sample_pandas_normal.csv', index_col=0)

df['sex'] = ['female', np.nan, 'male', 'male', 'female', 'male']
df['rank'] = [2, 1, 1, 0, 2, 0]

print(df)
#          age state  point     sex  rank
# name
# Alice     24    NY     64  female     2
# Bob       42    CA     92     NaN     1
# Charlie   18    CA     70    male     1
# Dave      68    TX     70    male     0
# Ellen     24    CA     88  female     2
# Frank     30    NY     57    male     0

pandas.get_dummies()的基本用法

指定 pandas.Series、array(Python 列表、NumPy 数组 ndarray 等)和 pandas.DataFrame 作为第一个参数数据。

无论哪种情况,都会返回 pandas.DataFrame 中的一个新对象。如果要更新原始对象,可以将其分配给原始对象,例如,如下所示。

df = pd.get_dummies(df)

将 pandas.Series 和数组指定为参数时

在 pandas.Series 和数组(Python 列表、NumPy 数组 ndarray 等)的情况下,类别名称将是列名称。

print(pd.get_dummies(df['sex']))
#          female  male
# name                 
# Alice         1     0
# Bob           0     0
# Charlie       0     1
# Dave          0     1
# Ellen         1     0
# Frank         0     1

print(pd.get_dummies(['male', 1, 1, 2]))
#    1  2  male
# 0  0  0     1
# 1  1  0     0
# 2  1  0     0
# 3  0  1     0

print(pd.get_dummies(np.arange(6)))
#    0  1  2  3  4  5
# 0  1  0  0  0  0  0
# 1  0  1  0  0  0  0
# 2  0  0  1  0  0  0
# 3  0  0  0  1  0  0
# 4  0  0  0  0  1  0
# 5  0  0  0  0  0  1

数组(Python 列表、NumPy 数组、ndarray 等)必须是一维数组。二维数组会导致错误。

# print(pd.get_dummies(np.arange(6).reshape((2, 3))))
# Exception: Data must be 1-dimensional

将 pandas.DataFrame 指定为参数时

对于pandas.DataFrame,默认情况下,数据类型dtype为object(主要是字符串)或category的所有列都是虚拟变量。

数值(int, float) 和Boolean bool 列不转换并保持不变。稍后将描述要虚拟化数值和布尔列时的设置。

在 pandas.DataFrame 的情况下,列名称将是原始列名称_类别名称。稍后将描述要更改的设置。

print(pd.get_dummies(df))
#          age  point  rank  state_CA  state_NY  state_TX  sex_female  sex_male
# name                                                                         
# Alice     24     64     2         0         1         0           1         0
# Bob       42     92     1         1         0         0           0         0
# Charlie   18     70     1         1         0         0           0         1
# Dave      68     70     0         0         0         1           0         1
# Ellen     24     88     2         1         0         0           1         0
# Frank     30     57     0         0         1         0           0         1

排除第一类:drop_first

如果你想虚拟k个类别,你只需要k-1个虚拟变量,但是get_dummies()函数默认将它们转换为k个虚拟变量。 如果参数 drop_first = True,则排除第一个类别并转换为 k-1 虚拟变量。

print(pd.get_dummies(df, drop_first=True))
#          age  point  rank  state_NY  state_TX  sex_male
# name                                                   
# Alice     24     64     2         1         0         0
# Bob       42     92     1         0         0         0
# Charlie   18     70     1         0         0         1
# Dave      68     70     0         0         1         1
# Ellen     24     88     2         0         0         0
# Frank     30     57     0         1         0         1

缺失值NaN虚拟化:dummy_na

默认情况下,缺失值 NaN 被排除和处理。

如果要将 NaN 作为一个类别作为虚拟变量,请设置参数 dummy_na = True。 此时,对于不包含 NaN 的列,也会生成 NaN 虚拟变量。所有元素都是0。

print(pd.get_dummies(df, drop_first=True, dummy_na=True))
#          age  point  rank  state_NY  state_TX  state_nan  sex_male  sex_nan
# name                                                                       
# Alice     24     64     2         1         0          0         0        0
# Bob       42     92     1         0         0          0         0        1
# Charlie   18     70     1         0         0          0         1        0
# Dave      68     70     0         0         1          0         1        0
# Ellen     24     88     2         0         0          0         0        0
# Frank     30     57     0         1         0          0         1        0

指定pandas.DataFrame的虚拟变量的列名:prefix,prefix_sep

以pandas.DataFrame为例,生成的虚拟变量的列名默认为原来的列名_类别名。

这可以通过参数 prefix 和 prefix_sep 进行更改。 类别名称。

参数前缀由字符串、字符串列表或字符串字典指定。

在字符串的情况下,所有前缀都是通用的。如果只想使用类别名称作为虚拟变量的列名称,请在空字符串’'中指定prefix和prefix_sep。

print(pd.get_dummies(df, drop_first=True, prefix='', prefix_sep=''))
#          age  point  rank  NY  TX  male
# name                                   
# Alice     24     64     2   1   0     0
# Bob       42     92     1   0   0     0
# Charlie   18     70     1   0   0     1
# Dave      68     70     0   0   1     1
# Ellen     24     88     2   0   0     0
# Frank     30     57     0   1   0     1

在列表和字典的情况下,需要为要保留原始列名的列指定值。如果列表或字典中的元素数与要虚拟的列数不匹配,则会发生错误。

print(pd.get_dummies(df, drop_first=True, prefix=['ST', 'sex'], prefix_sep='-'))
#          age  point  rank  ST-NY  ST-TX  sex-male
# name                                             
# Alice     24     64     2      1      0         0
# Bob       42     92     1      0      0         0
# Charlie   18     70     1      0      0         1
# Dave      68     70     0      0      1         1
# Ellen     24     88     2      0      0         0
# Frank     30     57     0      1      0         1

print(pd.get_dummies(df, drop_first=True, prefix={
    
    'state': 'ST', 'sex': 'sex'}, prefix_sep='-'))
#          age  point  rank  ST-NY  ST-TX  sex-male
# name                                             
# Alice     24     64     2      1      0         0
# Bob       42     92     1      0      0         0
# Charlie   18     70     1      0      0         1
# Dave      68     70     0      0      1         1
# Ellen     24     88     2      0      0         0
# Frank     30     57     0      1      0         1

在pandas.DataFrame 中指定列的虚拟数字/布尔列:columns

如上所述,在pandas.DataFrame的情况下,默认情况下只有数据类型为dtype object(主要是字符串)或category的列被虚拟化。

如果在参数列中指定要虚拟的列的列名,则还可以虚拟数字或布尔列。未指定的列不会被虚拟化。

print(pd.get_dummies(df, drop_first=True, columns=['sex', 'rank']))
#          age state  point  sex_male  rank_1  rank_2
# name                                               
# Alice     24    NY     64         0       0       1
# Bob       42    CA     92         0       1       0
# Charlie   18    CA     70         1       1       0
# Dave      68    TX     70         1       0       0
# Ellen     24    CA     88         0       0       1
# Frank     30    NY     57         1       0       0

如果您不想在列表中指定大量列,使用 astype() 将您想要虚拟的数字或布尔列的数据类型转换为对象可能更容易。

请注意,如果将列的数据类型转换为对象并更新原始对象,则在使用该列进行数值运算或布尔运算时需要返回原始类型。

df['rank'] = df['rank'].astype(object)
print(pd.get_dummies(df, drop_first=True))
#          age  point  state_NY  state_TX  sex_male  rank_1  rank_2
# name                                                             
# Alice     24     64         1         0         0       0       1
# Bob       42     92         0         0         0       1       0
# Charlie   18     70         0         0         1       1       0
# Dave      68     70         0         1         1       0       0
# Ellen     24     88         0         0         0       0       1
# Frank     30     57         1         0         1       0       0

任意数字化每个类别(级别):map()方法

如果要将字符串分类的每个类别替换为任意数值,而不是像虚拟变量那样为每个类别(级别)生成 0 或 1 列,请使用 map() 方法。

指定字典 {original value:converted value} 作为参数。

print(df['state'].map({
    
    'CA': 0, 'NY': 1, 'TX': 2}))
# name
# Alice      1
# Bob        0
# Charlie    0
# Dave       2
# Ellen      0
# Frank      1
# Name: state, dtype: int64

map() 是pandas.Series 的一个方法。如果要处理pandas.DataFrame的列并更新值,可以如下赋值给原列。

df['state'] = df['state'].map({
    
    'CA': 0, 'NY': 1, 'TX': 2})
print(df)
#          age  state  point     sex rank
# name                                   
# Alice     24      1     64  female    2
# Bob       42      0     92     NaN    1
# Charlie   18      0     70    male    1
# Dave      68      2     70    male    0
# Ellen     24      0     88  female    2
# Frank     30      1     57    male    0

猜你喜欢

转载自blog.csdn.net/qq_18351157/article/details/118106709