【问题标题】:R: Apply function to only "factor" variablesR:仅将函数应用于“因子”变量
【发布时间】:2021-10-15 13:51:26
【问题描述】:

我正在使用 R。我有一个包含字符变量和数字变量的数据集 - 我正在尝试用“0”替换此数据中的所有 NA 和空值。

最近,我学会了如何将因子变量中的“NA”值替换为 0 (R: replacing <NA> within factor variables as 0):

# "df" is the dataset, "a" is the variable
#Include 0 in the levels for "a" variable
levels(df$a) <- c(levels(df$a), 0)
#Replace NA to 0
df[is.na(df)] <- 0

现在,我正在尝试学习如何将此命令应用于“df”中的每个因子变量。

我学会了如何识别所有包含“因子”变量的列:

is.fact <- sapply(df, is.factor)

从这里,有没有办法运行这个命令

levels(df$a) <- c(levels(df$a), 0)

对于数据中的每个因子变量?

目前,我正计划为所有变量手动重写此命令,例如:

levels(df$a) <- c(levels(df$a), 0)
levels(df$b) <- c(levels(df$b), 0)
levels(df$c) <- c(levels(df$c), 0)

然后运行以下行:

df[is.na(df)] <- 0

但我试图找到一种更快的方法来做到这一点。

有人知道怎么做吗?有人可以告诉我一个更快的方法来解决这个问题吗?

谢谢

【问题讨论】:

    标签: r dataframe function data-manipulation


    【解决方案1】:

    您可以lapply 一次,然后对每一列进行处理。在处理每一列的过程中,您可以检查该列是否为Factor。如果是因子向量,则进行转换,如果不直接返回列。

    这是带有示例data.frame 的完整代码。

    df <- data.frame(
        a = factor(c(1, 2, 4, NA, 5, 6)),
        b = c("a", "b", "c", NA, "e", "f"),
        c = factor(c(NA, 1, 2, 3, 4, 5))
    )
    
    replaceNA <- function (df) {
        result <- lapply(df, function(col) {
            if (is.factor(col)) {
                levels(col) <- c(levels(col), 0)
            }
            return (col)
        })
        result[is.na(result)] <- 0
        return (result)
    }
    
    replaceNA(df)
    

    【讨论】:

      【解决方案2】:

      这是一个基本的 R 选项(从 @Martin Gal 借用 df

      list2DF(
        lapply(
          df,
          function(x) {
            if (is.factor(x)) {
              replace(`levels<-`(x, c(levels(x), 0)), is.na(x), 0)
            } else {
              x
            }
          }
        )
      )
      

      给了

         a b    A
      1  k x    d
      2  u e    b
      3  d h    o
      4  y s    t
      5  j y    u
      6  t k    m
      7  j 0    i
      8  p 0    e
      9  o z    d
      10 0 s    t
      11 o a    v
      12 h q    t
      13 c d    g
      14 m b    o
      15 b d    b
      16 0 y    j
      17 w 0    h
      18 n t    b
      19 i 0 <NA>
      20 b z    x
      21 g 0    g
      22 h d    s
      23 v a    j
      24 w 0    b
      25 y 0    c
      26 n 0    i
      27 l j    b
      28 g 0    b
      29 f h    h
      30 0 0    i
      

      【讨论】:

        【解决方案3】:

        您可以使用 dplyrtidyr 来完成此任务:

        library(dplyr)
        library(tidyr)
        
        df %>% 
          tibble() %>% 
          mutate(across(where(is.factor), ~replace_na(`levels<-`(.x, c(levels(.x), 0)), 0)))
        

        主要思想是使用dplyracross 函数来查找带有factors 的每一列并将您的函数应用于此。这里使用的第二个想法是

        levels(df$a) <- c(levels(df$a), 0)
        

        一样
        `levels<-`(df$a, c(levels(df$a), 0))
        

        赋值只是我们可以在管道中使用的一种特殊函数。所以代码应用到

        df <- structure(list(a = structure(c(9L, 16L, 3L, 19L, 8L, 15L, 8L, 
        14L, 13L, NA, 13L, 6L, 2L, 11L, 1L, NA, 18L, 12L, 7L, 1L, 5L, 
        6L, 17L, 18L, 19L, 12L, 10L, 5L, 4L, NA), .Label = c("b", "c", 
        "d", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "t", 
        "u", "v", "w", "y"), class = "factor"), b = structure(c(11L, 
        4L, 5L, 9L, 12L, 7L, NA, NA, 13L, 9L, 1L, 8L, 3L, 2L, 3L, 12L, 
        NA, 10L, NA, 13L, NA, 3L, 1L, NA, NA, NA, 6L, NA, 5L, NA), .Label = c("a", 
        "b", "d", "e", "h", "j", "k", "q", "s", "t", "x", "y", "z"), class = "factor"), 
            A = c("d", "b", "o", "t", "u", "m", "i", "e", "d", "t", "v", 
            "t", "g", "o", "b", "j", "h", "b", NA, "x", "g", "s", "j", 
            "b", "c", "i", "b", "b", "h", "i")), class = "data.frame", row.names = c(NA, 
        -30L))
        

        返回

        # A tibble: 30 x 3
           a     b     A    
           <fct> <fct> <chr>
         1 k     x     d    
         2 u     e     b    
         3 d     h     o    
         4 y     s     t    
         5 j     y     u    
         6 t     k     m    
         7 j     0     i    
         8 p     0     e    
         9 o     z     d    
        10 0     s     t    
        11 o     a     v    
        12 h     q     t    
        13 c     d     g    
        14 m     b     o    
        15 b     d     b    
        16 0     y     j    
        17 w     0     h    
        18 n     t     b    
        19 i     0     NA   
        20 b     z     x    
        21 g     0     g    
        22 h     d     s    
        23 v     a     j    
        24 w     0     b    
        25 y     0     c    
        26 n     0     i    
        27 l     j     b    
        28 g     0     b    
        29 f     h     h    
        30 0     0     i
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-01-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-06-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多