【问题标题】:filtering each column of a data frame an put NA for unmatched values过滤数据框的每一列,将 NA 用于不匹配的值
【发布时间】:2024-01-13 11:21:01
【问题描述】:

我有一张如下表:

     [,1]  [,2] [,3]    [,4]   [,5] 
[1,]  a     A   0.06    0.31   -1.5
[2,]  b     B  -0.75    0.2    0.02
[3,]  c     C   1.58   -0.02    1.5 

我想在第 3 到第 5 列设置一个截断值,以找到绝对值大于 1 的单元格。

我也想用绝对值填充匹配值,不匹配条件的单元格用“NA”填充。

为此,我使用了 dplyr 包中的过滤器功能,但无法获得所需的结果。有谁知道我该怎么做。

这是输出必须的样子:

     [,1]  [,2] [,3]    [,4]   [,5] 
[1,]  a     A   NA       NA    1.5
[2,]  b     B   NA       NA     NA
[3,]  c     C   1.58     NA    1.5 

谢谢!

【问题讨论】:

    标签: r dataframe filter dplyr subset


    【解决方案1】:

    可以尝试使用dplyr::mutate_at as:

    library(dplyr)
    
    df %>% mutate_at(vars(3:5), funs(ifelse(abs(.) > 1, abs(.), NA_integer_)))
    

    或者如果数据有factor 类型的列尝试:

    df %>% mutate_at(vars(3:5), funs(ifelse(abs(as.numeric(as.character(.))) > 1, 
                                         abs(as.numeric(as.character(.))), NA_integer_)))
    
    #   V1 V2   V3 V4  V5
    # 1  a  A   NA NA 1.5
    # 2  b  B   NA NA  NA
    # 3  c  C 1.58 NA 1.5
    

    数据:

    df <- read.table(text="
    a     A   0.06    0.31   -1.5
    b     B  -0.75    0.2    0.02
    c     C   1.58   -0.02    1.5",
    stringsAsFactors = FALSE)
    

    【讨论】:

    • 当我尝试您的代码时,我收到此错误:mutate_impl(.data, dots) 中的错误:评估错误:'abs' 对因子没有意义。我尝试使用以下代码将因子转换为数字: df
    • @yas.f 似乎您的数据只有几列factor。如果是这样,请尝试我更新的答案。
    【解决方案2】:

    这是一个base R 选项

    df[3:5] <- lapply(df[3:5], function(x) replace(x, abs(x) < 1, NA))
    df
    #  V1 V2   V3 V4   V5
    #1  a  A   NA NA -1.5
    #2  b  B   NA NA   NA
    #3  c  C 1.58 NA  1.5
    

    数据

    df <- structure(list(V1 = c("a", "b", "c"), V2 = c("A", "B", "C"), 
    V3 = c(0.06, -0.75, 1.58), V4 = c(0.31, 0.2, -0.02), V5 = c(-1.5, 
    0.02, 1.5)), .Names = c("V1", "V2", "V3", "V4", "V5"), 
    class = "data.frame", row.names = c(NA, -3L))
    

    【讨论】:

      【解决方案3】:

      您可以只使用这样的 R 基函数来做到这一点:

      > dat <- read.table(text="a     A   0.06    0.31   -1.5
       b     B  -0.75    0.2    0.02
       c     C   1.58   -0.02    1.5", header=FALSE)
      > dat[,3:5][abs(dat[,3:5])<=1]<-NA
      > dat[,3:5] <- abs(dat[,3:5])
      > dat
        V1 V2   V3 V4  V5
      1  a  A   NA NA 1.5
      2  b  B   NA NA  NA
      3  c  C 1.58 NA 1.5
      

      【讨论】:

      • 谢谢。我尝试了您的代码,但它给了我以下错误:数据框中的非数字变量:我使用 as.numeric 函数但我收到此错误:[&lt;-.data.frame(*tmp*,abs(as.numeric(dat[ , 3:5]))
      • @JilberUrbina 我认为您必须使用两步过程。首先将abs值小于1的单元格替换为NA。然后将 rest 替换为 abs 值。
      【解决方案4】:
       dat <- read.table(text="
              a     A   0.06    0.31   -1.5
              b     B  -0.75    0.2    0.02
              c     C   1.58   -0.02    1.5", header=FALSE)
      
       dat[3:5] = abs(dat[3:5])
      
       is.na(dat[3:5]) = dat[3:5]<1
      
       dat
        V1 V2   V3 V4  V5
      1  a  A   NA NA 1.5
      2  b  B   NA NA  NA
      3  c  C 1.58 NA 1.5
      

      【讨论】:

        最近更新 更多