我有两个带有相同列名的小标题:
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中删除。
答案 0 :(得分:2)
我们可以使tb1
和tb2
中的行相等,然后将两个相等大小的数据帧相乘。
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
如果tb1
和tb2
中的列顺序不同,我们可以先做
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