【问题标题】:Create a Model for Dummy Variables为虚拟变量创建模型
【发布时间】:2017-01-05 18:37:47
【问题描述】:

从变量var1 的训练数据集开始:

var1
A
B
C
D

我想创建一个模型(我们称之为dummy_model1),然后将训练数据集转换为:

var1_A  var1_B  var1_C  var1_D
1       0       0       0
0       1       0       0
0       0       1       0
0       0       0       1

此功能(或类似功能)存在于R 中的dummies 包和Pandas 中的get_dummies 中,甚至存在于SQL 中的case 语句中。

然后我希望能够将dummy_model1 应用于新数据集:

var1
C
7
#
A

并得到以下输出:

var1_A  var1_B  var1_C  var1_D
0       0       1       0
0       0       0       0
0       0       0       0
1       0       0       0

我知道我可以在 SQL 中使用“case”语句执行此操作,但鉴于我有大约 2,000 个变量,我很想自动化该过程。此外,新数据集几乎总是有“坏”数据(例如,上例中的7#)。

有点语言不可知论(只要它是开源的),但更喜欢PythonR。请注意,数据超过 500GB,因此限制了我的一些选择。提前致谢。

【问题讨论】:

  • 在 R 中,您可以从了解 model.matrix 函数开始。
  • 您实际上是在问如何将新数据转换为与您从训练数据中创建的虚拟变量编码(可能来自get_dummies)一致?所以 A 和 C 被 7 编码而 # 被忽略?如果是,我会发布一个简短的 Python 答案。
  • 如果“坏”数据是指“不同”数据而不是“代码破坏”数据,那不是问题。我假设您的 500gb 数据集不适合内存(如果可以,请纠正我)。如果没有,请进行信封计算(或仅检查)您的单列 var1 是否适合内存。
  • @FrankB。谢谢;我现在有一个更好的图片。我会把解决方案留给那些已经在写的人。
  • 明白了。然后我将编写我的解决方案,假设 var1 适合内存。

标签: python r dummy-variable


【解决方案1】:

假设var1 自己适合内存,这是一个可能的解决方案:

首先,读入var1

接下来,使用get_dummies 将所有“训练”类别编码为虚拟变量。将列名存储为列表或数组。

然后,读取训练数据集的前几行以获取列名并将它们存储为列表(或者如果您已经知道这些,则可以跳过此步骤)。

创建一个包含虚拟变量列名和相关其他列的新列表或数组(这可能只是数据集中除var1 之外的每一列)。这将是最后的列编码。

然后,读入您的测试数据。使用get_dummies 在您的测试数据中编码var1,知道它可能缺少类别或有无关的类别。然后重新索引数据以匹配最终的列编码。

重新索引后,您将得到一个测试数据集,其中包含与您的训练 var1 一致的 var1 假人。

举例说明:

import pandas as pd
import numpy as np

training = pd.DataFrame({
        'var1': ['a','b','c'],
        'other_var':[4,7,3],
        'yet_another':[8,0,2]
    })

print training
   other_var var1  yet_another
0          4    a            8
1          7    b            0
2          3    c            2

test = pd.DataFrame({
        'var1': ['a','b','q'],
        'other_var':[9,4,2],
        'yet_another':[9,1,5]
    })

print test
   other_var var1  yet_another
0          9    a            9
1          4    b            1
2          2    q            5


var1_dummied = pd.get_dummies(training.var1, prefix='var1')
var_dummy_columns =  var1_dummied.columns.values

print var_dummy_columns
array(['var1_a', 'var1_b', 'var1_c'], dtype=object)

final_encoding_columns = np.append(training.drop(['var1'], axis = 1).columns, var_dummy_columns)

print final_encoding_columns
array(['other_var', 'yet_another', 'var1_a', 'var1_b', 'var1_c'], dtype=object)


test_encoded = pd.get_dummies(test, columns=['var1'])

print test_encoded
   other_var  yet_another  var1_a  var1_b  var1_q
0          9            9       1       0       0
1          4            1       0       1       0
2          2            5       0       0       1

test_encoded_reindexed = test_encoded.reindex(columns = final_encoding_columns, fill_value=0)

print test_encoded_reindexed
   other_var  yet_another  var1_a  var1_b  var1_c
0          9            9       1       0       0
1          4            1       0       1       0
2          2            5       0       0       0

这应该是您想要的,这取决于您的问题和 cmets 中的预期输出。

如果测试数据很容易放入内存中,您可以轻松地将其扩展到多个变量。只需为您要编码的每个训练变量保存然后迭代更新final_encoding_columns。然后在重新索引测试数据时将所有这些列传递给columns= 参数。使用完整的 final_encoding_columns 重新索引,您应该一切就绪。

【讨论】:

  • 感谢 Nick,并为让您编写自定义代码而道歉。我希望有人已经将它放入一个包裹中,但我猜他们没有给出你的答案。
  • 完全不用担心。这实际上是当我将使用编码分类变量的模型投入生产时经常出现的问题,因此我有一些易于访问的骨架代码。
【解决方案2】:

试一试:

# first set the variable to factor with levels specified
df$var1 <- factor(df$var1, levels = LETTERS[1:4])

model.matrix(data = df, ~var1-1)
#  var1A var1B var1C var1D
#1     0     0     1     0
#4     1     0     0     0

# or even 
sapply(LETTERS[1:4], function(x) as.numeric(x==df$var1))
#     A B C D
#[1,] 0 0 1 0
#[2,] 0 0 0 0
#[3,] 0 0 0 0
#[4,] 1 0 0 0

【讨论】:

  • 我看到的 2 个(可能的)问题是数据大小问题(导入 500GB+ CSV),而且我不知道每个变量预先包含什么(文档参差不齐)。
  • 不一定要手动检查每个变量。即使我有文档说唯一的值是“A”、“B”和“C”,它仍然很可能实际上是“X”、“Y”和“Z”
猜你喜欢
  • 2023-03-27
  • 2021-11-01
  • 2017-10-23
  • 2018-04-06
  • 2020-01-31
  • 1970-01-01
  • 2015-06-09
  • 2017-02-24
  • 2012-09-27
相关资源
最近更新 更多