1
votes

Comment puis-je multiplier deux tibbles par des noms de colonne

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.


0 commentaires

4 Réponses :


4
votes

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


0 commentaires

1
votes

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.


0 commentaires

0
votes

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


0 commentaires

0
votes

Une autre solution de base R consiste à utiliser 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

tel que

res <- cbind(tb2[1],kronecker(rep(1,nrow(tb2)),as.matrix(tb1[-1]))*tb2[-1])


0 commentaires