【问题标题】:Need to change data.table columns' value from "Yes" ,"No" to 1,0需要将 data.table 列的值从“是”、“否”更改为 1,0
【发布时间】:2020-01-31 17:08:24
【问题描述】:

我有一个大约 80 万行的数据表对象。其中的某些列具有 Yes/No 值。我想分别改成1/0。这里workable_data 是我的data.table 对象:

我的修改代码(看起来太简单了):

yes_No_to_1 <- function(x){
  sapply(x,function(x){
    if(x =='Yes'){
      1
      }else{
        0}
    })
} 

sapply(workable_data[,product,with=FALSE],yes_No_to_1)

但是有两个问题:(1) 需要很长时间;(2) 我想以 data.table 的方式永久更改 workable_data 中的值。

您可以使用以下方法重现示例数据:

product <- c("HasProduct1","HasProduct2","HasProduct3","HasProduct4","HasProduct5","HasProduct6","HasProduct7","HasProduct8","HasProduct9","HasProduct10")
workable_data <- as.data.table(data.frame(x=sample(1:100),sapply(product,function(x){x <-sample(c("Yes","No"),10000,replace = T)})))

我认为有更好的方法来实现这一点,但我似乎无法弄清楚,我也很感激任何关于优化我的功能的建议(这将是最后的手段)。这个样本数据所花费的时间对于 10k 行来说是相当糟糕的。

  user    system elapsed 
   6.21    0.00    6.25 

【问题讨论】:

  • 使用factor()将列转换为因子,然后as.numeric()得到数字(workable_data[,product,with=F]$HasProduct1 %&gt;% factor() %&gt;% as.numeric) - 1
  • my_cols = grep("^HasProduct", names(DT), value=TRUE); DT[, (my_cols) := lapply(.SD, function(x) +(x=="Yes")), .SDcols=my_cols] 是一种方式。我建议从包的教程材料开始,以了解它的用途及其常用语法:github.com/Rdatatable/data.table/wiki/Getting-started
  • 我刚刚开始使用 data.table 。我正在浏览这些示例并且可以做一些基本的事情,但你所做的事情远远超出了我的理解。谢谢。让我测试并理解
  • @Frank 我不太明白匿名函数中“+”的使用。请您解释一下
  • 嘿,不,+ 只是我们最近在 SO 上使用的一个 hack,因为人们通常要求将他们的假人编码为 1/0 而不是 TRUE/FALSE。这就像“代码高尔夫”(笔画/字符越少越好)

标签: r data.table


【解决方案1】:

您可以使用 data.table 中的 set 功能来做到这一点:

1:创建一个列名向量,您希望在其中将Yes 更改为1,将No 更改为0(就像@Frank 在 cmets 中所说)

cols <- grep("^HasProduct", names(DT), value = TRUE)

2: 使用以下 for(...) set(...) 实现更改值(正如 @Arun 在 cmets 中正确指出的那样,您也可以使用 as.integer 而不仅仅是 +):

for (col in cols) set(DT, j = col, value = +(DT[[col]] == "Yes"))

这会导致:

> DT
        x HasProduct1 HasProduct2 HasProduct3 HasProduct4 HasProduct5 HasProduct6 HasProduct7 HasProduct8 HasProduct9 HasProduct10
    1: 23           0           1           0           1           0           0           1           0           0            0
    2: 74           1           0           1           1           0           1           1           1           1            1
    3: 35           1           1           0           0           0           1           1           1           0            1
    4:  7           1           1           1           1           0           1           1           0           0            1
    5: 92           0           1           1           1           1           1           0           1           1            0
   ---                                                                                                                            
 9996: 56           0           0           1           0           1           0           0           0           1            0
 9997: 59           1           0           1           1           0           1           1           1           1            0
 9998: 85           0           1           0           1           1           1           1           1           1            1
 9999: 93           1           0           0           0           0           0           0           0           1            1
10000: 29           0           1           1           0           0           1           0           1           1            1

时间安排:

   user  system elapsed 
  0.007   0.000   0.007 

使用过的数据:

set.seed(654)
product <- c("HasProduct1","HasProduct2","HasProduct3","HasProduct4","HasProduct5","HasProduct6","HasProduct7","HasProduct8","HasProduct9","HasProduct10")
DT <- as.data.table(data.frame(x=sample(1:100),sapply(product,function(x){x <-sample(c("Yes","No"),10000,replace = T)})))

【讨论】:

  • 不错。我会使用as.integer() 而不是神秘的+
【解决方案2】:

这样的东西应该可以工作,虽然我还没有测试过:

data[, zero_one := ifelse(test = (data[, yes_no] == "yes"), yes = 1, no = 0)]

zero_one 是使用:= 分配的新变量,右侧的计算应用于数据表中的每个值。

【讨论】:

  • 他们如何为所有 10 列做到这一点?
  • 我相信data[,lapply(.SD, function(x) x=='yes')]
【解决方案3】:

在 R 中,因子在内部被视为 1,2,3...整数,对应于因子内的每个级别。 “否”按字母顺序出现在“是”之前,因此“否”== 1L,“是”== 2L(“L”只是将数字设置为整数)。我们可以从一个因子中保留整数并减去 1L 得到“否”== 0L,“是”== 1L。

与上面的 Jaap 相比,这种方法的优点是可以以相同的方式转换具有任意级别数的因子。计算时间基本相同,尤其是对于较大的表。

require(data.table)

# generate example data
set.seed(2020)
product <- c("HasProduct1","HasProduct2","HasProduct3","HasProduct4","HasProduct5","HasProduct6","HasProduct7","HasProduct8","HasProduct9","HasProduct10")
DT <- as.data.table(data.frame(x=sample(1:100),sapply(product,function(x){x <-sample(c("Yes","No"),10000,replace = T)})))

# define the columns to process
cols <- grep("^HasProduct", names(DT), value=TRUE)

# this is another data.table way to do it
DT[, (cols) := lapply(.SD, function(x) return(as.integer(as.factor(x)) - 1L)), .SDcols = cols]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    • 2021-06-14
    • 1970-01-01
    • 2020-10-03
    • 2012-02-27
    相关资源
    最近更新 更多