Как сделать базовое левое внешнее соединение с data.table в R?
У меня есть таблица данных a и b, которую я разделил на below
с помощью b <.5 и above
с b > .5:
DT = data.table(a=as.integer(c(1,1,2,2,3,3)), b=c(0,0,0,1,1,1))
above = DT[DT$b > .5]
below = DT[DT$b < .5, list(a=a)]
Я хотел бы сделать левое внешнее соединение между above
и below
: для каждого a
в above
, подсчитайте количество строк в below
. Это эквивалентно следующему в SQL:
with dt as (select 1 as a, 0 as b union select 1, 0 union select 2, 0 union select 2, 1 union select 3, 1 union select 3, 1),
above as (select a, b from dt where b > .5),
below as (select a, b from dt where b < .5)
select above.a, count(below.a) from above left outer join below on (above.a = below.a) group by above.a;
a | count
---+-------
3 | 0
2 | 1
(2 rows)
Как сделать то же самое с data.tables? Это то, что я пробовал до сих пор:
> key(below) = 'a'
> below[above, list(count=length(b))]
a count
[1,] 2 1
[2,] 3 1
[3,] 3 1
> below[above, list(count=length(b)), by=a]
Error in eval(expr, envir, enclos) : object 'b' not found
> below[, list(count=length(a)), by=a][above]
a count b
[1,] 2 1 1
[2,] 3 NA 1
[3,] 3 NA 1
Я также должен быть более конкретным в том, что я уже пробовал merge
, но это пробивает память в моей системе (а набор данных занимает около 20% моей памяти).
Ответы
Ответ 1
Посмотрите, что это дает вам что-то полезное. Ваш пример слишком разрежен, чтобы сообщить мне, что вы хотите, но, похоже, это может быть таблица значений above$a
, которые также находятся в below$a
table(above$a[above$a %in% below$a])
Если вы также хотите, чтобы обратные... значения не были в below
, тогда это сделало бы это:
table(above$a[!above$a %in% below$a])
И вы можете связать их:
> c(table(above$a[above$a %in% below$a]),table(above$a[!above$a %in% below$a]) )
2 3
1 2
Обычно table
и %in%
работают с достаточно маленькими отпечатками и быстры.
Ответ 2
Поскольку вы, кажется, используете пакет data.table
: проверьте ?merge.data.table
.
Я не использовал его, но кажется, что это может сделать то, что вы хотите:
merge(above, below, by="a", all.x=TRUE, all.y=FALSE)
Ответ 3
Я думаю, что это проще:
setkey(above,a)
setkey(below,a)
Левое внешнее соединение:
above[below, .N]
регулярное соединение:
above[below, .N, nomatch=0]
полное внешнее соединение со счетами:
merge(above,below, all=T)[,.N, by=a]
Ответ 4
В конце концов я нашел способ сделать это с помощью data.table
, который, по моему мнению, более естественен для меня, чем DWin table
, хотя YMMV:
result = below[, list(count=length(b)), by=a]
key(result) = 'a'
result = result[J(unique(above$a))]
result$count[is.na(result$count)] = 0
Я не знаю, может ли это быть более компактным. Мне особенно хотелось сделать что-то вроде result = below[J(unique(above$a)), list(count=length(b))]
, но это не работает.