【问题标题】:Conditional Subset of Rows from Two Separate Data Frames来自两个单独数据帧的条件行子集
【发布时间】:2017-08-06 01:15:14
【问题描述】:

我有两个数据框,它们的排列使得 qseqid 和 sseqid 在每一行中都是相同的:

Data frame 1

  qseqid               evalue bitscore
1 ENSDARP00000000004.2 1e-162 469.0
2 ENSDARP00000000005.6 0e+00 856.0
3 ENSDARP00000000042.9 0e+00 1272.0
4 ENSDARP00000000069.7 3e-111 333.0
5 ENSDARP00000000070.5 2e-11 58.2

Data frame 2

  sseqid               evalue bitscore
1 ENSDARP00000000004.2 9e-160 462.0
2 ENSDARP00000000005.6 0e+00 821.0
3 ENSDARP00000000042.9 0e+00 1293.0
4 ENSDARP00000000069.7 4e-102 310.0
5 ENSDARP00000000070.5 1e-11 58.2

我想创建一个单一的数据帧,其中包含数据帧中具有最低 e 值的行(这样我可以保留位分数),如果两个数据帧中的 evalues 相同,请跳过那一排。我的结果如下所示:

1 ENSDARP00000000004.2 1e-162 469.0
2 ENSDARP00000000069.7 3e-111 333.0
5 ENSDARP00000000070.5 1e-11 58.2

最小示例代码:

qseqid <- c("ENSDARP00000000004.2",
            "ENSDARP00000000005.6",
            "ENSDARP00000000042.9",
            "ENSDARP00000000069.7",
            "ENSDARP00000000070.5")
evalue <- c(1e-162, 0e+00, 0e+00, 3e-111, 2e-11 )
bitscore <- c(469.0, 856.0, 1272.0, 333.0, 58.2)
df_1 <- data.frame(qseqid, evalue, bitscore)

sseqid <- c("ENSDARP00000000004.2",
            "ENSDARP00000000005.6",
            "ENSDARP00000000042.9",
            "ENSDARP00000000069.7",
            "ENSDARP00000000070.5")  
evalue <- c(9e-160, 0e+00, 0e+00, 4e-102, 1e-11)
bitscore <- c(462.0, 821.0, 1293.0, 310.0, 58.2)
df_2 <- data.frame(sseqid, evalue, bitscore)

我的第一个想法是使用 ifelse(),但是这种方法失败了,因为我不是 确定如果数据帧之间的 evalues 相等,如何传递该行,并且我不确定如何从任一数据帧返回成功的行。

filtered_df <- ifelse(df_1$evalue == df_2$evalue,
                  next, ifelse(df_1$evalue < df_2s$evalue, 
                      successful df_1 row here,
                      successful df_2 row here)) 

我的第二个想法是使用 rbind() 组合数据帧,然后使用 aggregate() 找到最小值,最后将结果合并成一个 单个数据框。然而,这并没有最终处理真实的数据集。它大约有 12k 行,我最终得到了太多重复值。一个优雅的解决方案将不胜感激。

【问题讨论】:

  • 射击,我刚刚意识到如果我想跳过相等的行,我可以将 == 设置为 !=。仍然需要弄清楚如何返回一行。

标签: r


【解决方案1】:
# Copying the first data.frame
df_3 <- df_1
# Replacing with the values from the second data.frame
# If the values in the second are less than in the first
m <- df_1$evalue > df_2$evalue
df_3[m,] <- df_2[m, ]

# Leave only unique values
df_4 <- df_3[df_1$evalue != df_2$evalue,]
df_4
#                 qseqid evalue bitscore
# 1 ENSDARP00000000004.2 1e-162    469.0
# 4 ENSDARP00000000069.7 3e-111    333.0
# 5 ENSDARP00000000070.5  1e-11     58.2

【讨论】:

  • 我在我的实际数据集上使用您的解决方案时遇到了这个错误:[&lt;-.data.frame(*tmp*, m, , value = list(sseqid = c(14L, 18L, :数据框的下标分配中不允许缺少值。有什么想法吗?是否可以通过遍历数据集来实现我的目标?
【解决方案2】:

这是一个使用函数式风格的选项。步骤 1)使用问题中描述的逻辑生成有效行的列表(作为列表),否则为 NULL。步骤 2) 过滤掉空列表。第 3 步)用答案恢复 data.frame。

#Step 1:
a <- mapply( function(name1,name2,evalue1,evalue2,bitscore1,bitscore2) {
               if( name1==name2 )
                 if ( evalue1 == evalue2 )
                   NULL
                 else {
                   minEvalue <- min(evalue1,evalue2)
                   keepBitScore <- ifelse(evalue1==minEvalue, bitscore1,bitscore2)
                   list(qseqid=name1,evalue=minEvalue,bitscore=keepBitScore)
                 }
              }, 
              df_1[,1],df_2[,1], df_1[,2],df_2[,2],df_1[,3],df_2[,3])

#Step 2:
Filter(Negate(function(x) is.null(unlist(x))), a)

#Step 3:
ans<-do.call(rbind.data.frame,a)

给予:

                 qseqid evalue bitscore
2  ENSDARP00000000004.2 1e-162    469.0
21 ENSDARP00000000069.7 3e-111    333.0
3  ENSDARP00000000070.5  1e-11     58.2

我的答案丢失了原始行名。我相信他们可以通过一些调整来保持。只要有可能,我就喜欢直截了当的功能风格。

【讨论】:

    【解决方案3】:

    这是一个使用 dplyr 包强大功能的好机会。

    首先,让我们为数据帧创建相同的标题,并将“qseqid”/“sseqid”保留为新变量。

    library(dplyr)
    
    df_1 <- df_1 %>% mutate('type' = 'qseqid') %>% rename('instance' = 'qseqid')
    df_2 <- df_2 %>% mutate('type' = 'sseqid') %>% rename('instance' = 'sseqid')
    

    然后,我们可以轻松地将数据帧绑定在一起,并通过以下方式对其进行处理:

    res <- df_1 %>% bind_rows(df_2) %>% 
    
        #calculate standart deviation of "evalue" within created groups
    
        group_by(instance) %>% mutate('diff_e' = sd(evalue)) %>% 
    
        #select rows with the following logic: std non-equal zero and select minimal within created groups
    
              filter(diff_e != 0 & evalue == min(evalue))
    

    有关 dplyr 的更多信息,请阅读以下书籍:http://r4ds.had.co.nz

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-10
      • 2020-07-22
      • 2013-06-14
      • 2017-01-26
      • 1970-01-01
      • 1970-01-01
      • 2019-10-13
      • 1970-01-01
      相关资源
      最近更新 更多