J'ai deux blocs de données, A et B. En BI, j'ai deux colonnes clés et pour chaque ligne de BI, je dois compter le nombre de lignes dans A correspondant à ces clés.
Je sais comment résoudre le problème en utilisant un for-loop mais cela prend une éternité et je me demandais s'il y avait une façon plus intelligente de le faire. Je suis encore assez nouveau sur R, vous devrez donc me pardonner si je manque une solution évidente.
Les blocs de données ont la structure suivante. Bien sûr, en réalité, les trames de données sont beaucoup plus grandes.
for (i in 1:nrow(B)) { B$count[i] <- sum(A$key1 == B$key1[i] & A$key2 == B$key2[i], na.rm = TRUE) }
J'ai utilisé la boucle for suivante et j'ai obtenu le résultat correct.
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")
3 Réponses :
En utilisant la même logique que vous mais sans boucle en utilisant 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
Voici une idée utilisant merge
,
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
qui donne,
# 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
Ajout de la solution data.table
pour terminer,
library(tidyverse) A %>% full_join(B, by = c('key1', 'key2')) %>% group_by(key1, key2) %>% summarise(count = sum(!is.na(value)))
Une option en base R
(similaire à l'option @Sotos tidyverse)
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
Ou avec data.table
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
Hein ... donc pas besoin de convertir les deux cadres en tables de données avant de fusionner? Un seul suffit?
@Sotos Oui, l'un d'entre eux suffit surtout l'extérieur
Vous avez tout d'abord mis à jour. Je laisserai aux gens le soin de comparer la mauvaise syntaxe data.table
à la bonne syntaxe :)