Как сделать базовое левое внешнее соединение с data.table в R? - PullRequest
3 голосов
/ 17 августа 2011

У меня есть таблицы данных a и b, которые я разделил на below с b <.5 и <code>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%моя память).

Ответы [ 4 ]

4 голосов
/ 18 августа 2011

Посмотрите, дает ли это вам что-нибудь полезное. Ваш пример слишком редок, чтобы сообщить мне, что вы хотите, но, похоже, это может быть таблица значений 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% занимают достаточно маленькие места и быстры.

4 голосов
/ 17 августа 2011

Поскольку вы, похоже, используете пакет data.table: отметьте ?merge.data.table.Я не использовал его, но, похоже, он может делать то, что вы хотите:

merge(above, below, by="a", all.x=TRUE, all.y=FALSE)
2 голосов
/ 27 апреля 2014

Я думаю, что это проще:

setkey(above,a)
setkey(below,a)

Левое внешнее объединение:

above[below, .N]

обычное соединение:

above[below, .N, nomatch=0]

полное внешнее соединение с количеством:

merge(above,below, all=T)[,.N, by=a]
1 голос
/ 18 августа 2011

В конце концов я нашел способ сделать это с 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))], но это не сработало.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...