【问题标题】:Add flags to columns according to a condition根据条件向列添加标志
【发布时间】:2019-04-12 11:44:46
【问题描述】:

假设你有一个这样的data.frame:

          FDR_1      Label_1     FDR_2      Label_2  
          0.001        NA        0.45         NA
          0.34         NA         6           NA
          0.2          NA         3           NA
          2            NA         2.5         NA
          4            NA        0.001        NA           

总共 10.000 行和 3000 列,并且您想要以下输出:

       FDR_1      Label_1     FDR_2      Label_2  
          0.001        NA        0.45         NA
          0.34         NA         6           Y
          0.2          NA         3           Y
          2            Y         2.5          Y
          4            Y        0.001         NA           

换句话说,您希望将 Y“标志”添加到 FDR* 列包含值 > 2 的行。

我试过这个:

lapply(mydf, function(x) ifelse(mydf[, grepl( "FDR" , names(mydf) ) > 2, .....) 

但我不知道如何继续添加标志。

谁能帮帮我?

提前谢谢你

【问题讨论】:

  • 我认为你的意思是 >= 2 否则 Label_1[4] 将是 NA

标签: r


【解决方案1】:

我们可以在base R 中使用

df1[!i1] <- 'Y'[(NA^(df1[i1] <= 2))]
df1
#   FDR_1 Label_1 FDR_2 Label_2
#1 0.001    <NA> 0.450    <NA>
#2 0.340    <NA> 6.000       Y
#3 0.200    <NA> 3.000       Y
#4 2.000    <NA> 2.500       Y
#5 4.000       Y 0.001    <NA>

在哪里

i1 <-  grepl("^FDR", names(df1))

数据

df1 <- structure(list(FDR_1 = c(0.001, 0.34, 0.2, 2, 4), Label_1 = c(NA, 
 NA, NA, NA, NA), FDR_2 = c(0.45, 6, 3, 2.5, 0.001), Label_2 = c(NA, 
 NA, NA, NA, NA)), class = "data.frame", row.names = c(NA, -5L
 ))

【讨论】:

  • 不错的一个。不知道NA^0 == 1,这可能有点反直觉
  • @thothal 谢谢。我应该使用ifelse 让它更容易理解
  • 需要注意的一点是 - 在它的所有优点中 - 此解决方案要求列按此特定顺序排列。更改为df1[, c(3, 2:1, 4)],代码会产生错误的结果。恕我直言,代码应该(几乎)从不依赖行或列的顺序。
  • @thothal 当然,我注意到了
【解决方案2】:

我们可以使用 base R 中的split.default 来拆分数字上的列,即

do.call(cbind, 
   lapply(split.default(df, gsub('\\D+', '',names(df))), function(i){
                                           i[2] <- replace(i[2], i[1] >= 2, 'Y'); i}))

#  1.FDR_1 1.Label_1 2.FDR_2 2.Label_2
#1   0.001      <NA>   0.450      <NA>
#2   0.340      <NA>   6.000         Y
#3   0.200      <NA>   3.000         Y
#4   2.000         Y   2.500         Y
#5   4.000         Y   0.001      <NA>

【讨论】:

    【解决方案3】:

    使用reshape 的循环“免费”基础R 变体:

    df <- structure(list(FDR_1   = c(0.001, 0.34, 0.2, 2, 4), 
                         Label_1 = c(NA, NA, NA, NA, NA), 
                         FDR_2   = c(0.45, 6, 3, 2.5, 0.001), 
                         Label_2 = c(NA, NA, NA, NA, NA)), 
                    class     = "data.frame", 
                    row.names = c(NA, -5L))
    
    mv <- lapply(split(names(df), 
                gsub("(.+)_\\d+", 
                     "\\1", 
                     names(df))), sort)
    
    data_long <- reshape(df, 
                         varying   = mv, 
                         direction = "long", 
                         v.names   = names(mv))
    data_long$Label[data_long$FDR >= 2] <- "Y"
    reshape(data_long)
    #     id FDR_1 Label_1 FDR_2 Label_2
    # 1.1  1 0.001    <NA> 0.450    <NA>
    # 2.1  2 0.340    <NA> 6.000       Y
    # 3.1  3 0.200    <NA> 3.000       Y
    # 4.1  4 2.000       Y 2.500       Y
    # 5.1  5 4.000       Y 0.001    <NA>
    

    【讨论】:

      【解决方案4】:

      你也可以试试tidyverse

      library(tidyverse)
      read.table(text="  FDR_1      Label_1     FDR_2      Label_2  
                0.001        NA        0.45         NA
                0.34         NA         6           NA
                0.2          NA         3           NA
                2            NA         2.5         NA
                4            NA        0.001        NA    ", header=T) %>% 
        rownames_to_column() %>% 
        gather(k, v, -rowname) %>% 
        separate(k, into = c("k1", "k2")) %>% 
        spread(k1, v) %>% 
        mutate(Label = ifelse(FDR >= 2, "Y", Label)) %>% 
        gather(k, v, -rowname, -k2) %>% 
        unite(k, k2, k) %>% # changing the colnames a little bit
        spread(k, v) %>% 
        select(-1)    
        1_FDR 1_Label 2_FDR 2_Label
      1 0.001    <NA>  0.45    <NA>
      2  0.34    <NA>     6       Y
      3   0.2    <NA>     3       Y
      4     2       Y   2.5       Y
      5     4       Y 0.001    <NA>
      

      【讨论】:

        猜你喜欢
        • 2023-03-30
        • 2021-12-02
        • 2020-06-09
        • 2021-09-29
        • 1970-01-01
        • 2022-11-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多