【问题标题】:How to loop over a data frame conditionally using R如何使用 R 有条件地循环数据帧
【发布时间】:2020-06-09 11:09:10
【问题描述】:

由于我是 R 循环的新手,我将感谢您对我的问题的帮助。 假设我有一个这样的数据框:

Family <- c('mir-1','mir-1','mir-3','mir-4','mir-4','LET-7', 'LET-7','mir-1','mir-4','LET-7')
Species <- c('hsa','chicken','hsa','hsa','chicken','hsa','hsa','chicken','chicken','hsa')
Tissue <- c('blood','liver','blood','blood','liver','skin','skin','skin','liver','nail')
star <- c('1','4','3','4','12','3','7','4','1','5') #numeric
mature <- c('9','6','8','1','7','3','4','2','8','9')  #numeric
df <- data.frame(Family,Species,Tissue,star,mature)

我的输出应该是这样的:

Family_ <- c('mir-1','mir-1','mir-3','mir-4','mir-4','LET-7', 'LET-7','mir-1','mir-4','LET-7')
Species_ <- c('hsa','chicken','hsa','hsa','chicken','hsa','hsa','chicken','chicken','hsa')
Tissue_ <- c('blood','liver','blood','blood','liver','skin','skin','skin','liver','nail')
star <- c('1','4','3','4','12','3','7','4','1','5') #numeric
mature <- c('9','6','8','1','7','3','4','2','8','9')  #numeric
total_count <- c('10','10','11','5','28','17','17','6','28','14')  #numeric
star_total <- c('1','4','3','4','13','10','10','4','13','5')  #numeric
mature_total <- c('9','6','8','1','15','7','7','2','15','9')  #numeric
df_new <- data.frame(Family_,Species_,Tissue_,star,mature,star_total,mature_total,total_count)

我想遍历each family in each tissue in each species。所以基本上对于第一列中特定组织和特定物种中的每个家庭(不删除重复的行)我想计算total_count &lt;- sum (mature) + sum (star)star_total &lt;- sum (star),@ 987654326@ * 添加一个额外的列 * 称为 rpm_mature 可以通过这种方式计算 rpm_mature &lt;- mature_total/total_count*10^6 (此列不包含在我的输出中)。因此,对于在相似物种的相似组织中具有相似家族的行,这些重复行的计算应该相同。也许我描述的不是很好,但如果你看一下可以理解的输出。谢谢

【问题讨论】:

    标签: r loops dataframe for-loop conditional-statements


    【解决方案1】:

    这是一种方法,我们通过Family, Species, Tissue 分组并进行计算:

    library(data.table)
    setDT(df)
    df[,":="(total_count = sum(mature) + sum(star),
             star_total = sum(star),
             mature_total = sum(mature),
             rpm_mature = mature_total/total_count*10^6),.(Family, Species, Tissue)]
    
    print(df)
    
        Family Species Tissue star mature total_count star_total mature_total rpm_mature
     1:  mir-1     hsa  blood    1      8           9          1            8   888888.9
     2:  mir-1 chicken  liver    4      5           9          4            5   555555.6
     3:  mir-3     hsa  blood    3      7          10          3            7   700000.0
     4:  mir-4     hsa  blood    4      1           5          4            1   200000.0
     5:  mir-4 chicken  liver    2      6           8          3           13  1625000.0
     6:  LET-7     hsa   skin    3      3           6          9            7  1166666.7
     7:  LET-7     hsa   skin    6      4          10          9            7   700000.0
     8:  mir-1 chicken   skin    4      2           6          4            2   333333.3
     9:  mir-4 chicken  liver    1      7           8          3           13  1625000.0
    10:  LET-7     hsa   nail    5      8          13          5            8   615384.6
    

    【讨论】:

    • 感谢您帮助我,但如果您查看第 6 行和第 7 行,它们具有相同的家族、相同的物种和相同的组织。所以它们的总数应该是 16(因为它们是相同的,所以应该打印这两行)。
    • 第 5 行和第 9 行也是如此
    • 因此,在此分析之后,如果我使我的行独一无二,那么我将为每个组织中每个物种的每个家庭获得正确的 total_count。
    【解决方案2】:

    这是tidyverse 方法 - 以防万一:

    library(tidyverse)
    
    df %>%
      mutate_at(c("star", "mature"), as.numeric) %>%
      group_by(Family, Species, Tissue) %>%
      mutate(total_count = sum(mature) + sum(star),
             star_total = sum(star),
             mature_total = sum(mature),
             rpm_mature = mature_total/total_count*10^6)
    

    输出

    # A tibble: 10 x 9
    # Groups:   Family, Species, Tissue [8]
       Family Species Tissue  star mature total_count star_total mature_total rpm_mature
       <fct>  <fct>   <fct>  <dbl>  <dbl>       <dbl>      <dbl>        <dbl>      <dbl>
     1 mir-1  hsa     blood      1      8           9          1            8    888889.
     2 mir-1  chicken liver      4      5           9          4            5    555556.
     3 mir-3  hsa     blood      3      7          10          3            7    700000 
     4 mir-4  hsa     blood      4      1           5          4            1    200000 
     5 mir-4  chicken liver      2      6          16          3           13    812500 
     6 LET-7  hsa     skin       3      3          16          9            7    437500 
     7 LET-7  hsa     skin       6      4          16          9            7    437500 
     8 mir-1  chicken skin       4      2           6          4            2    333333.
     9 mir-4  chicken liver      1      7          16          3           13    812500 
    10 LET-7  hsa     nail       5      8          13          5            8    615385.
    

    编辑

    如果您有兴趣开发循环方法,您可以执行以下操作来获得相同的结果:

    df$star <- as.numeric(df$star)
    df$mature <- as.numeric(df$mature)
    
    df <- cbind(df, total_count = NA, star_total = NA, mature_total = NA)
    
    for (Fam in df$Family) {
      for (Spec in df$Species) {
        for (Tiss in df$Tissue) {
          res <- df[df$Family == Fam & df$Species == Spec & df$Tissue == Tiss,]
          if (nrow(res) > 0) {
            res$total_count = sum(res$mature) + sum(res$star)
            res$star_total = sum(res$star)
            res$mature_total = sum(res$mature)
            df[df$Family == Fam & df$Species == Spec & df$Tissue == Tiss,] <- res
          }
        }
      }
    }
    
    df$rpm_mature = df$mature_total/df$total_count*10^6
    

    【讨论】:

    • 感谢您的回答。 for loop 也可以这样做吗?
    • 比你多
    猜你喜欢
    • 2021-06-25
    • 1970-01-01
    • 2013-07-12
    • 2019-07-27
    • 1970-01-01
    • 2015-11-14
    • 2016-08-18
    • 2021-11-23
    • 2021-08-27
    相关资源
    最近更新 更多