如何将两个小标题乘以列名

时间:2019-12-30 03:29:18

标签: r dplyr tibble

我有两个带有相同列名的小标题:

tb1:

   date        a     b     c     d     e
  <date>     <dbl> <dbl> <dbl> <dbl> <dbl>
1 2017-06-01  113.  182.  21.0  31.9  111.

tb2:

   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的每一行乘以tb1中的相应数字,是否可以通过dplyr或其他方式简单地实现这一点?我需要保留tb2中的日期,但我已将其从tb1中删除。

4 个答案:

答案 0 :(得分:2)

我们可以使tb1tb2中的行相等,然后将两个相等大小的数据帧相乘。

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

如果tb1tb2中的列顺序不同,我们可以先做

tb1 <- tb1[match(names(tb2), names(tb1))]

,然后使用上面的内容。

数据

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"))

答案 1 :(得分:0)

为了很好地进行缩放并处理不匹配或乱序的列以及不同的行数,我将尝试重塑数据。如果将两个数据集都设置为长格式,则将具有a,b,c,...列,可用于将数据集连接在一起。保留所需的列,然后重新调整为宽格式。

我选择使用左联接,以便保留tb2中的每一行(具有更多行的那一行),即使它在tb1中没有匹配的行也是如此。我还设置了后缀参数,以使其更清楚每列来自哪个数据集。

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.

答案 2 :(得分:0)

另一种选择是在sweep?sweep的数字列上使用base-R的tb1(检查tb2的使用情况),假设这些列在相同的顺序:

## 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

答案 3 :(得分:0)

另一种基本的R解决方案是使用kronecker()tb1中的行扩展为与tb2[-1]大小相同的矩阵,即:

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

如此

> 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