【问题标题】:Fast method in R of obtaining a value from one column based on searched value in another?R中基于另一列中的搜索值从一列中获取值的快速方法?
【发布时间】:2019-06-28 14:17:16
【问题描述】:

我有两个数据框,其中一个有两个标识符的大列表:

rsid uniq_id
rs796086906 1_13868_G_A
rs546169444 1_14464_T_A
rs6682375 1_14907_G_A
rs6682385 1_14930_G_A

其中一个包含两个标识符之一:

V1 V2 V3 V4 V5 V6
1    1_10439_A_AC  0 10439  A    AC
1    1_13417_CGAGA_C  0 13417  C CGAGA
1    1_14907_G_A  0 14907  G     A

我想要的是用第一个数据帧中相应的第二个 ID 替换第二个数据帧中的 ID(我也想不出一个简洁的方式来表达这个问题的标题,因此为什么它的措辞如此尴尬以及为什么我可能无法找到重复项)。即:

V1 V2 V3 V4 V5 V6
1    1_10439_A_AC  0 10439  A    AC
1    1_13417_CGAGA_C  0 13417  C CGAGA
1    rs6682375  0 14907  G     A

我目前的解决方案是使用for ... if循环如下:

for (x in 1:nrow(df2)){

    if (df2$V2[x] %in% df1$uniq_id){

        df2$V2[x] = df1$rsid[x]
    }
}

但是,由于这两个文件都非常大,我认为这可能是一种非常低效的方法,我想知道是否有更快的方法。

有人建议使用 match() 函数可能会更快,但鉴于 R 文档表明 %in% 实际上更直观,而且我对它缺乏经验,我不确定如何在不同的方式。

任何帮助表示赞赏。

【问题讨论】:

    标签: r for-loop match


    【解决方案1】:

    这是一个更新连接,在 data.table 术语中。假设第一个表名为df,第二个表名为df2

    library(data.table)
    setDT(df)
    setDT(df2)
    
    df2[df, on = .(V2 = uniq_id), V2 := rsid]
    
    df2
    #    V1              V2 V3    V4 V5    V6
    # 1:  1    1_10439_A_AC  0 10439  A    AC
    # 2:  1 1_13417_CGAGA_C  0 13417  C CGAGA
    # 3:  1       rs6682375  0 14907  G     A
    

    使用的数据

    df <- fread('
    rsid uniq_id
    rs796086906 1_13868_G_A
    rs546169444 1_14464_T_A
    rs6682375 1_14907_G_A
    rs6682385 1_14930_G_A
    ')
    df2 <- fread('
    V1 V2 V3 V4 V5 V6
    1    1_10439_A_AC  0 10439  A    AC
    1    1_13417_CGAGA_C  0 13417  C CGAGA
    1    1_14907_G_A  0 14907  G     A
    ')
    

    【讨论】:

    • 我可以检查一下,setDT() 函数在这里的用途是什么?据我了解,它会更改数据表中数据框中的数据,但这样做的目的是什么?特别是当我读入我实际使用的数据时:fread(x, data.table = FALSE)
    • 方括号[ 是一个函数,并且该函数有方法,这意味着它是一个函数,根据它所作用的对象的类调用不同的函数。将df 标记为data.table 会使[ 调用[.data.table 函数,而不是通常的[,即[.data.frame。这些方法之间的一个区别是它允许您进行更新连接。 (尝试在没有setDT 的情况下运行代码,你会得到一个错误)。实际上setDT 不仅仅改变了[ 的行为,但这是与这个答案相关的部分。欲了解更多信息,请参阅?setDT
    • 嗯,好的。所以这是关于 [ ] 与数据表与数据帧相比的不同行为?另外,实际上,为了记录,在上面的示例中,您肯定不需要setDT() 函数,因为您实际上最初将文件作为数据表读取,然后实际上也没有使用该函数更改它们? (因为你肯定会这样做:df = setDT(df)
    • 这就是我在这个答案中使用它的原因,是的。但这不是 setDT 所做的唯一事情
    • 是的,我确实不需要它来运行此答案中的代码,因为我使用fread 读入了它们。我只是这样做,因为我假设您已经加载了它们,即您没有使用 fread 阅读它们。
    【解决方案2】:

    使用基数 r 的方法。使用dplyr 也很容易执行此操作,如果需要,它是left_join 函数。

    df <- data.table::fread('
    rsid uniq_id
    rs796086906 1_13868_G_A
    rs546169444 1_14464_T_A
    rs6682375 1_14907_G_A
    rs6682385 1_14930_G_A
    ')
    df2 <- data.table::fread('
    V1 V2 V3 V4 V5 V6
    1    1_10439_A_AC  0 10439  A    AC
    1    1_13417_CGAGA_C  0 13417  C CGAGA
    1    1_14907_G_A  0 14907  G     A
    ')
    
    df2 <- merge(df2,df,by.x = c("V2"),by.y = c("uniq_id"),all.x = TRUE)
    df2$V2 <- ifelse(!is.na(df2$rsid),df2$rsid,df2$V2)
    df2$rsid <- NULL
    
    df2
    
    #                 V2 V1 V3    V4 V5    V6
    # 1:    1_10439_A_AC  1  0 10439  A    AC
    # 2: 1_13417_CGAGA_C  1  0 13417  C CGAGA
    # 3:       rs6682375  1  0 14907  G     A
    

    【讨论】:

    • 啊哈,我明白了!因此,您通过uniq_id 将这两个文件相互合并,然后简单地将rsid 移过来。优雅的。我现在唯一真正的问题是这种方法是否会比 IceCreamToucan 的更快。另外,据我了解,dplyr 实际上也很快,您知道使用它是否会更好吗?
    • IceCreamToucan 应该更快。不过,有些人一开始就对 data.table 感到困惑,所以我包含了一个基本方法。
    • 我使用的逻辑也适用于 dplyr,但您可以使用 df2 %&gt;% left_join(df,by = c("V2" = "uniq_id")) %&gt;% mutate(V2 = ifelse(!is.na(rsid),rsid,V2)) %&gt;% select(-rsid)。这篇旧帖子显示了 data.table 更新表的速度有多快:stackoverflow.com/a/51577964/8485287
    猜你喜欢
    • 2021-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-24
    • 2021-01-18
    • 2021-06-22
    相关资源
    最近更新 更多