交错联接/新分组/带数据的R联接。表';sx[Y]语法

交错联接/新分组/带数据的R联接。表';sx[Y]语法,r,data.table,R,Data.table,我有两个数据。表:示例,资源 resources通过primary和secondaryid与samples连接。 我希望首先通过主id将资源中的信息与示例表相结合,并且仅当这产生NA时,我才希望使用同一个表中的辅助资源(在一个data.table命令链中) 预期的结果将是: # joined tables: name info # primary secondary 1: "a" "I" 2: "b" "I" 3: "c" "J" 第一次通过primary连接很容易,它会产

我有两个
数据。表
示例,资源

resources
通过
primary
secondary
id与
samples
连接。 我希望首先通过主id将资源中的信息与示例表相结合,并且仅当这产生NA时,我才希望使用同一个表中的辅助资源(在一个data.table命令链中)

预期的结果将是:

# joined tables:
   name info  # primary secondary
1:  "a"  "I"
2:  "b"  "I"
3:  "c"  "J"
第一次通过
primary
连接很容易,它会产生

# Update:
samples <- data.table(name = letters[1:3], 
                      primary = c(17, 0, 18), 
                      secondary = c(55, 42, 42))
resources <- data.table(primary = 17:19, 
                        secondary = c(42, NA, 43), 
                        info = LETTERS[9:11])
# first join:
setkey(samples, primary)
setkey(resources, primary)
samples[resources]

   name info  # primary secondary
1:  "a"  "I"
2:  "b"   NA
3:  "c"  "J"
#更新:

示例我认为在一个命令链中执行此操作太棘手,但我有一个解决方案供您使用:

### First step
samples[resources[samples, nomatch = 0], info := info]
samples

   name primary secondary info
1:    b       0        42   NA
2:    a      17        55    I
3:    c      18        42    J

### Second step
setkey(samples, secondary)
setkey(resources, secondary)
## create new column info1
samples[resources[samples[is.na(info)],
                  list(info1 = unique(info)), by = .EACHI],
        info1 := info1]
## merge it to samples, where info is NA
samples[is.na(info), info := info1]
## remove info1 (and maybe other unused columns)
samples[, info1 := NULL]
## sort samples by name
setkey(samples, name)
samples

   name primary secondary info
1:    a      17        55    I
2:    b       0        42    I
3:    c      18        42    J
HTH

~g

这将是一条链,包含两个对
资源的调用,其中一个在幕后重新设置密钥

library(data.table)
samples <- data.table(name = letters[1:3], 
                      primary = c(17, 0, 18), 
                      secondary = c(55, 42, 42))
resources <- data.table(primary = 17:19, 
                        secondary = c(42, NA, 43), 
                        info = LETTERS[9:11])
setkey(samples, primary)
setkey(resources, primary)
samples[resources, info := i.info
        ][, .(name, info),, secondary
          ][resources[, info,, secondary], info := ifelse(is.na(info), i.info, info)
            ][, secondary := NULL]

库(data.table)

示例虽然你可以在一行上完成,但我认为这模糊了你所做的事情的含义,使事情难以阅读/理解/调试/记住你在一个月内到底做了什么,这简直是个坏主意

更小、更容易消化的块是imo的发展方向:

setkey(samples, primary)
setkey(resources, primary)
samples[resources, info := i.info]

setkey(samples, secondary)
setkey(resources, secondary)
samples[resources, info := ifelse(is.na(info), i.info, info)]

samples
#   name primary secondary info
#1:    b       0        42    I
#2:    c      18        42    J
#3:    a      17        55    I

# keep going with tertiary and so on if you like

正如@nachti在评论中指出的,根据您的数据,您可能需要为1.9.5之前的版本添加
allow.cartesian=TRUE

也许可以通过包含构造
样本
资源
的代码来轻松复制?不是
数据。表
友好,但只是以防万一有用:想要在一个命令链中完成它是非常困难的misguided@eddi --是的。我认为这是一个关键的观察结果。@JanGorecki——听起来你有一个对你很有用的习惯用语,所以我建议你还是坚持下去吧!我碰巧发现“更小的块”方法更容易解析——但这仅仅是因为我更习惯于它,并且认为在一条可能很长的线上完成所有事情没有内在的优点。我明白了,当你第一次发现链接/管道时,在一条线上做很多事情是很酷的,但在最初的兴奋消失之后,你需要缩小规模,并意识到你实际上并不想把整个脚本都放在一行上。你必须添加
by=.EACHI
,因为dt 1.9.4:
samples[resources,info:=ifelse(is.na(info),i.info,info),by=.EACHI]
更多信息,请参阅@nachti no,这是不正确的-上面是使用1.9.5运行的(“have to”part不正确-您可以添加它,但这不会改变结果,它可能会也可能不会导致性能差异-我不确定它会朝哪个方向发展)在1.9.4中,我在vecseq中得到错误(f_uuuuuuu,len_uuuuuu,if(allow.cartesian | notjoin)NULL else as.integer(max(nrow(x)):Join结果在4行中;超过3=max(nrow(x),nrow(I)).检查i中是否存在重复的键值,每个键值都会一次又一次地加入x中的同一组。如果没有问题,请尝试包括
j
并删除
by
(不包括by)因此,j为每个组运行,以避免大量分配。如果您确实希望继续,请使用allow.cartesian=TRUE重新运行。否则,请在FAQ、Wiki、Stack Overflow和datatable帮助中搜索此错误消息以获取建议。Good point@eddi!
allow.cartesian=TRUE
的速度几乎是
by=.EACHI
的两倍。另请参见基准测试。我喜欢分别预定义
I
j
命令的建议,这可能有助于在更复杂的情况下使代码更易于阅读。我将结合@eddi和@nachti的建议使用此策略。
lkp2 <- quote(resources[, info,, secondary])
lkp2_formula <- quote(info := ifelse(is.na(info), i.info, info))
setkey(samples, primary)
samples[resources, info := i.info
        ][, .(name, info),, secondary
          ][eval(lkp2), eval(lkp2_formula)
            ][, secondary := NULL]
setkey(samples, primary)
setkey(resources, primary)
samples[resources, info := i.info]

setkey(samples, secondary)
setkey(resources, secondary)
samples[resources, info := ifelse(is.na(info), i.info, info)]

samples
#   name primary secondary info
#1:    b       0        42    I
#2:    c      18        42    J
#3:    a      17        55    I

# keep going with tertiary and so on if you like