J'ai deux tibbles avec les mêmes noms de colonne:
tb1:
date a b c d e <date> <dbl> <dbl> <dbl> <dbl> <dbl> 1 2016-05-01 122. 106. 23.9 43.7 93.5 2 2016-06-01 117. 111. 20.8 41.6 111. 3 2016-07-01 116. 94.4 22.5 41.0 92.4
tb2:
date a b c d e <date> <dbl> <dbl> <dbl> <dbl> <dbl> 1 2017-06-01 113. 182. 21.0 31.9 111.
Je veux multiplier chaque ligne de tb2 par le nombre respectif de tb1, y a-t-il un moyen simple de le faire avec dplyr ou autrement? Je dois conserver les dates de tb2 mais je les avais supprimées de tb1.
4 Réponses :
Nous pouvons rendre les lignes de tb1
et tb2
égales, puis multiplier les deux dataframes de taille égale.
tb1 <- structure(list(date = structure(1L, .Label = "2017-06-01", class = "factor"), a = 113, b = 182, c = 21, d = 31.9, e = 111), class = "data.frame", row.names = "1") tb2 <- structure(list(date = structure(1:3, .Label = c("2016-05-01", "2016-06-01", "2016-07-01"), class = "factor"), a = c(122, 117, 116), b = c(106, 111, 94.4), c = c(23.9, 20.8, 22.5), d = c(43.7, 41.6, 41), e = c(93.5, 111, 92.4)), class = "data.frame", row.names = c("1", "2", "3"))
Si le les colonnes dans tb1
et tb2
ne sont pas dans le même ordre, nous pouvons d'abord faire
tb1 <- tb1[match(names(tb2), names(tb1))]
puis utiliser ce qui précède.
cbind(tb2[1], tb1[rep(1, nrow(tb2)), -1] * tb2[-1]) # date a b c d e #1 2016-05-01 13786 19292.0 501.9 1394.03 10378.5 #2 2016-06-01 13221 20202.0 436.8 1327.04 12321.0 #3 2016-07-01 13108 17180.8 472.5 1307.90 10256.4
Pour bien mettre à l'échelle et gérer les colonnes non concordantes ou dans le désordre et le nombre différent de lignes, j'essaierais de remodeler les données. Si vous transformez les deux ensembles de données dans des formats longs, vous aurez des colonnes de a, b, c, ... que vous pouvez utiliser pour joindre les ensembles de données ensemble. Conservez les colonnes dont vous avez besoin et remodelez-les au format large.
J'ai choisi d'utiliser une jointure à gauche pour que chaque ligne de tb2 (celle avec le plus de lignes) soit conservée, même si elle n'a pas de ligne correspondante dans tb1. J'ai également défini l'argument suffixe pour indiquer plus clairement de quel ensemble de données provient chaque colonne.
library(dplyr) library(tidyr) left_join( pivot_longer(tb2, -date), pivot_longer(tb1, -date), by = "name", suffix = c("2", "1") ) %>% mutate(value = value1 * value2) %>% select(date = date2, name, value) %>% pivot_wider() #> # A tibble: 3 x 6 #> date a b c d e #> <fct> <dbl> <dbl> <dbl> <dbl> <dbl> #> 1 2016-05-01 13786 19292 502. 1394. 10378. #> 2 2016-06-01 13221 20202 437. 1327. 12321 #> 3 2016-07-01 13108 17181. 472. 1308. 10256.
Une autre option consiste à utiliser le sweep
de base-R (vérifiez ? sweep
pour son utilisation) sur les colonnes numériques de tb1
et tb2
en supposant que les colonnes sont dans le même ordre:
## sweep multiplication tb3 <- sweep(data.matrix(tb2)[, -1], MARGIN = 2, STATS = data.matrix(tb1)[, -1], FUN = "*") ## convert back to data.frame cbind(date = tb2[, 1], as.data.frame(tb3)) #> date a b c d e #> 1 2016-05-01 13786 19292.0 501.9 1394.03 10378.5 #> 2 2016-06-01 13221 20202.0 436.8 1327.04 12321.0 #> 3 2016-07-01 13108 17180.8 472.5 1307.90 10256.4
Une autre solution de base R consiste à utiliser tel que kronecker ()
pour développer la ligne de tb1
en une matrice de même taille de tb2 [-1] , c'est-à-dire:
> res
date a b c d e
1 2016-05-01 13786 19292.0 501.9 1394.03 10378.5
2 2016-06-01 13221 20202.0 436.8 1327.04 12321.0
3 2016-07-01 13108 17180.8 472.5 1307.90 10256.4
res <- cbind(tb2[1],kronecker(rep(1,nrow(tb2)),as.matrix(tb1[-1]))*tb2[-1])