Как выполнить «подсчет» для нескольких строк во фрейме данных? - PullRequest
0 голосов
/ 10 января 2019

У меня есть два фрейма данных, A и B. В B у меня есть два ключевых столбца, и для каждой строки в B мне нужно подсчитать количество строк в A, соответствующих этим ключам.

Я знаю, как решить проблему, используя цикл for, но это занимает вечность, и мне было интересно, есть ли более разумный способ сделать это. Я все еще новичок в R, так что вы должны простить меня, если я пропущу какое-то очевидное решение.

Кадры данных имеют следующую структуру. Конечно, в действительности кадры данных намного больше.

A <- data.frame(c(1, 2, 1), c(2, 1, 2), c("alpha", "bravo", "charlie")) 
colnames(A) <- c("key1", "key2", "value")

B <- data.frame(c(1, 2, 3), c(2, 1, 3), NA)
colnames(B) <- c("key1", "key2", "count")

Я использовал следующий цикл for и получил правильный результат.

for (i in 1:nrow(B)) {
  B$count[i] <- sum(A$key1 == B$key1[i] & A$key2 == B$key2[i], na.rm = TRUE)
}

Однако запуск кода занял много времени, и я подозреваю, что есть лучший способ сделать это. Буду признателен за любую помощь!

Ответы [ 3 ]

0 голосов
/ 10 января 2019

Вот идея с использованием merge,

library(tidyverse)

A %>% 
 full_join(B, by = c('key1', 'key2')) %>% 
 group_by(key1, key2) %>% 
 summarise(count = sum(!is.na(value)))

что дает,

# A tibble: 3 x 3
# Groups:   key1 [?]
   key1  key2 count
  <dbl> <dbl> <int>
1     1     2     2
2     2     1     1
3     3     3     0

Добавление решения data.table для завершения,

library(data.table)

setDT(A)[setDT(B), on = c('key1', 'key2')][, 
          .(count = sum(!is.na(value))), by = c('key1', 'key2')]

#   key1 key2 count
#1:    1    2     2
#2:    2    1     1
#3:    3    3     0
0 голосов
/ 10 января 2019

Параметр в base R (аналогично параметру @Sotos tidyverse)

aggregate(cbind(count = !is.na(value)) ~ key1 + key2, merge(A, B, all = TRUE), sum)
#    key1 key2 count
#1    2    1     1
#2    1    2     2
#3    3    3     0

Или с data.table

library(data.table)
setDT(A)[B, .(count = sum(!is.na(value))), on = .(key1, key2), by = .EACHI]
#   key1 key2 count
#1:    1    2     2
#2:    2    1     1
#3:    3    3     0
0 голосов
/ 10 января 2019

Используя ту же логику, что и вы, но без цикла, используя mapply

B$count <- mapply(function(x, y) 
      sum(x == A$key1 & y == A$key2, na.rm = TRUE), B$key1, B$key2)

B
#  key1 key2 count
#1    1    2     2
#2    2    1     1
#3    3    3     0
...