【问题标题】:Subsetting dataframe with logical matrix and vector使用逻辑矩阵和向量对数据框进行子集
【发布时间】:2021-03-22 12:54:21
【问题描述】:

对编码还是很陌生,我一直在遇到子集问题。在这种情况下,我的目标是从我的数据框中删除 NA 值。

col1 <- c("text", NA, "text", NA)
col2 <- c(NA, "text", "text", NA)
col3 <- c("text", NA, "text", NA)
col4 <- c(17, 22, NA, NA)
col5 <- c(3, NA, 3, 17)

df <- data.frame(col1, col2, col3, col4, col5)

当我只使用data[is.na(data)] &lt;- 0data[is.na(data)] &lt;- "" 时,我得到一个错误,我理解这是因为我将错误类型的值分配给错误的列类型。没有'numeric'空字符串,也没有整数值为0的字符串。

我想要的是将数字列中的所有 NA 转换为 0,将字符列中的所有 NA 转换为“”。我想出了如何从逻辑上解决问题的两个部分:

is.na(df)

>       col1  col2  col3  col4  col5
> [1,] FALSE  TRUE FALSE FALSE FALSE
> [2,]  TRUE FALSE  TRUE FALSE FALSE
> [3,] FALSE FALSE FALSE FALSE FALSE
> [4,]  TRUE  TRUE  TRUE FALSE FALSE

unlist(lapply(df, is.numeric), use.names=FALSE)

> [1] FALSE FALSE FALSE  TRUE  TRUE

现在有了这个,当然,我可以简单地编写一个 for 循环来遍历每个循环,确定一列是否为数字,然后在该列中相应地替换 NA。同样,如果我理解正确,我还可以扩展 unlist 产生的向量并将其转换为 20 个元素的向量和子集 df[ x == y ] &lt;- 0 and df[ x != y] &lt;- "" 或者我可以创建几个新的数据帧,相应地更改 NA,然后重新组合。

但是必须有一种更简单的方法来做到这一点。我猜这是我将继续遇到的问题,所以我希望而不是仅仅得到一个解决方案,我实际上可以理解如何“正确”地做到这一点(在 R 中可能会给我 5 个人的 8 条建议)。

【问题讨论】:

    标签: r


    【解决方案1】:

    您可以分别处理数字列和字符列。

    char_cols <- sapply(df, is.character)
    num_cols <- sapply(df, is.numeric)
    
    df[char_cols][is.na(df[char_cols])] <- ''
    df[num_cols][is.na(df[num_cols])] <- 0
    df
    
    #  col1 col2 col3 col4 col5
    #1 text      text   17    3
    #2      text        22    0
    #3 text text text    0    3
    #4                   0   17
    

    【讨论】:

    • 简单多了哈哈!不错!
    • 是的。就是这个。我不知道为什么我无法解决这个问题。只需使用中间变量逐步编写即可。一旦它起作用,您总是可以返回并通过嵌套函数来删除变量。谢谢。
    【解决方案2】:

    您可以根据列类型使用dplyr 中的mutate_if 替换NA

    library(dplyr)
    
    df %>%
      mutate_if(is.numeric, ~replace(.x, is.na(.x), 0)) %>%
      mutate_if(is.character, ~replace(.x, is.na(.x), ""))
    

    输出:

      col1 col2 col3 col4 col5
    1 text      text   17    3
    2      text        22    0
    3 text text text    0    3
    4                   0   17
    

    在 R 基础中实现这一点的可能方法:

    # Identify the numeric and character columns
    num_cols <- sapply(df, class) == "numeric"
    char_cols <- sapply(df, class) == "character"
    
    # Replace NA accordingly
    apply(df[, num_cols], 2, function(col) replace(col, is.na(col), 0))
    apply(df[, char_cols], 2, function(col) replace(col, is.na(col), ''))
    

    【讨论】:

    • 谢谢。并且可以看到它是如何工作的,但我真的不明白 mutate_if 语句的语法。首先它将每个单独的向量传递给函数是数字的,但是 ~ 符号和 .x 表示什么?
    • 不客气! mutate_if 仅当列与条件匹配时(例如,如果它是数字),才会将函数应用于每一列。 ~ 只是指定我们正在传递一个函数(在我们的例子中,replace),其中.x 是列。它独立处理每一列 (.x)。让我知道是否足够清楚。
    • 您也可以将~replace(.x, is.na(.x), 0) 替换为~ifelse(is.na(.x), 0, .x),它应该可以工作。
    【解决方案3】:

    如果您将带有字符串的数据框定义为关闭的因素,那么您可以简单地对整个数据框进行子集化以将NA 值替换为空字符串:

    df <- data.frame(col1, col2, col3, col4, col5,
                     stringsAsFactors=FALSE)
    df[is.na(df)] <- ""
    df
    
      col1 col2 col3 col4 col5
    1 text      text   17    3
    2      text        22     
    3 text text text         3
    4                       17
    

    【讨论】:

    • 谢谢。我注意到我的专栏被强制考虑因素,但不确定我能阻止这种情况。也就是说,独立于这个解决方案,我将如何同时对具有逻辑向量和矩阵的数据帧进行子设置,
    猜你喜欢
    • 2015-01-17
    • 2021-06-20
    • 2018-05-03
    • 1970-01-01
    • 2018-09-06
    • 1970-01-01
    • 1970-01-01
    • 2021-03-26
    相关资源
    最近更新 更多