【问题标题】:Applying same factor levels to multiple variables with differing amount of levels in R将相同的因子水平应用于 R 中具有不同水平数量的多个变量
【发布时间】:2021-04-15 03:05:43
【问题描述】:

我有一个 data.table168 variables8,278 observations。变量69:135 最初存储为字符串。他们应该成为区域假人,我想最终达到 2 级(=是,公司在这里经营)和 1 级(=否,公司不在这里经营)。问题在于原始变量中有三种不同的输入组合:1)“TRUE”、“1”、“0”、“FALSE”、2)“TRUE”、“FALSE”和 3)“1” ,“0”。此外,大约。 5 个变量只有一个值,“0”或“1”。这里给出一个例子:

#generating replicable data
structure(list(
  region1 = structure(c("TRUE", "FALSE", "0", "1", NA), class = "character"), 
  region2 = structure(c("1", "1", "0", NA, NA), class = "character"), 
  region3 = structure(c(NA, "FALSE", "TRUE", NA, "FALSE"), class = "character"),
  region4 = structure(c(NA, "0", "0", NA, "0"), class = "character")),
  .Names = c("region1", "region2", "region3", "region4"), row.names = c(NA, 5), class = "data.table")

#this gives:
#   region1 region2 region3 region4
#1    TRUE       1    <NA>    <NA>
#2   FALSE       1   FALSE       0
#3       0       0    TRUE       0
#4       1    <NA>    <NA>    <NA>
#5    <NA>    <NA>   FALSE       0                                                                                      

我正在寻找一种方法,一次将所有变量的“TRUE”和“1”替换为 2,将“FALSE”和“0”替换为 1。所以想要的结果是:

#   region1 region2 region3 region4
#1:       2       2      NA      NA
#2:       1       2       1       1
#3:       1       1       2       1
#4:       2      NA      NA      NA
#5:      NA      NA       1       1

我已经看过了

Apply factor levels to multiple columns with missing factor levelsChange level of multiple factor variables.

但是,这对我没有帮助。

我使用嵌套的ifelse() 命令尝试了以下操作:

library(data.table)
library(forcats)

check <- cbind(dt[1:68], as.data.table(apply(dt[69:135], 2, function(x) {
  ifelse("1" %in% x & "TRUE" %in% x,
         fct_collapse(x,
                      "2" = c("TRUE",
                              "1"),
                      "1" = c("FALSE",
                              "0")
         ),
         ifelse("1" %in% x & !("TRUE" %in% x),
                fct_collapse(x,
                             "2" = "1",
                             "1" = "0"),
                fct_collapse(x,
                             "2" = "TRUE",
                             "1" = "FALSE"
                )))
}
)), dt[136:168]) 

但是前面的代码没有给我想要的结果。它运行了,但我收到一条警告消息,并且在检查各个变量时,它们仍以原始输入的字符串形式存储。

# examples of warnings
1: Unknown levels in `f`: TRUE, FALSE
2: Unknown levels in `f`: TRUE, FALSE
3: Unknown levels in `f`: TRUE, FALSE
4: Unknown levels in `f`: 0
5: Unknown levels in `f`: TRUE, FALSE
6: Unknown levels in `f`: TRUE, FALSE
7: Unknown levels in `f`: 0

单独使用以及不与fct_collapse嵌套的ifelse() 命令结合使用时:

#the ifelse statement works
ifelse("TRUE" %in% dt$region1, 2, "FALSE")
ifelse(5 %in% dt$region1, 2, "FALSE")

#also the nested ifelse statement works
ifelse("1" %in% dt$region1 & "TRUE" %in% dt$region1,
              0,
              ifelse("1" %in% dt$region1 & !("TRUE" %in% dt$region1),
                     1,
                     2
              ))


ifelse("1" %in% dt$region2 & "TRUE" %in% dt$region2,
               0,
               ifelse("1" %in% dt$region2 & !("TRUE" %in% dt$region2),
                      1,
                      2
               ))

有人知道如何解决这个问题吗?

非常感谢您提前提供的任何建议!

【问题讨论】:

    标签: r data.table factors levels


    【解决方案1】:

    这是一种在for 循环中调用set() 的方法。

    library(data.table)
    
    f <- function(x){
      x <- as.character(x)
      i1 <- x %in% c("TRUE", "1")
      i0 <- x %in% c("FALSE", "0")
      x[which(i1)] <- "2"
      x[which(i0)] <- "1"
      as.integer(x)
    }
    
    for (j in seq_along(dt)) set(dt, j = j, value = f(dt[[j]]))
    
    dt
    #   region1 region2 region3 region4
    #1:       2       2      NA      NA
    #2:       1       2       1       1
    #3:       1       1       2       1
    #4:       2      NA      NA      NA
    #5:      NA      NA       1       1
    

    感谢jangorecki's comment 一个更简单的方法是

    dt[, names(dt) := lapply(dt, f)]
    

    【讨论】:

    • 我认为您可以删除for 循环并传递set(dt,, names(dt), lapply(dt, f)),不是吗?或者只是lapply(dt, f) :)
    • @jangorecki 谢谢,请参阅编辑。发表评论,我会回复它。
    • 非常感谢 Rui Barradas 和 @jangorecki 指出了进一步的简化方法。这容易多了!使用函数和 dt[, names(dt[, 69:135]) := lapply(dt[, 69:135], adjust_factor_levels)] 有效。 :)
    猜你喜欢
    • 1970-01-01
    • 2017-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多