#r #dataframe #multiple-columns #multiplication #wei&hted-avera&e
#r #фрейм данных #многоколоночный #умножение #средневзвешенное значение
Вопрос:
У меня есть следующие два примера data.frame
.
set.seed(12345)
df1 = data.frame(a=c(rep("a",8), rep("b",5), rep("c",7), rep("d",10)),
b=rnorm(30, 6, 2),
c=rnorm(30, 12, 3.5),
d=rnorm(30, 8, 3)
)
df2 = data.frame(p=c("b", "c", "d"),
q=c(1.43, 2.14, -2.03)
)
Я хотел бы создать новый, data.frame
используя базовые данные в df1
и средневзвешенное значение, используя коэффициенты умножения в df2
. Новый результат df3
будет таким же, как df1
, но с добавлением нового столбца со значениями: среднее значение по строке («b», умноженное на 1,43 «c», умноженное на 2,14, «d», умноженное на -2,03), так что результатом будет df3:
df3 = data.frame(a=c(rep("a",8), rep("b",5), rep("c",7), rep("d",10)),
b=rnorm(30, 6, 2),
c=rnorm(30, 12, 3.5),
d=rnorm(30, 8, 3),
new=c("24.8645275","44.67937096","29.68621196","19.26714231",
"25.23142628","27.65882406","11.98590475","-4.92298683",
"27.29998443","23.47463009","25.80746763","10.16714534",
"17.52916576","12.33418399","13.73084634","25.55675733",
"-0.13100614","26.26381852","22.69296138","2.86696252",
"12.27184531","30.41901753","18.43221894","1.12637556",
"2.51020245","13.89381723","17.7266222","27.83995036",
"32.569782","-5.04627832")
)
Как я мог бы это сделать, пожалуйста?
Комментарии:
1. Вам нужно среднее значение по строке или просто взвешенную сумму? Вывод, который вы показываете в
df3
, представляет собой взвешенную сумму2. Да, спасибо, что спросили :). Ну, средневзвешенное значение.
Ответ №1:
Одним dplyr
вариантом может быть:
df1 %&&t;%
rowwise() %&&t;%
mutate(new = sum(across(df2$p) * df2$q))
a b c d new
<fct&&t; <dbl&&t; <dbl&&t; <dbl&&t; <dbl&&t;
1 a 7.17 14.8 8.45 24.9
2 a 7.42 19.7 3.97 44.7
3 a 5.78 19.2 9.66 29.7
4 a 5.09 17.7 12.8 19.3
5 a 7.21 12.9 6.24 25.2
6 a 2.36 13.7 2.50 27.7
7 a 7.26 10.9 10.7 12.0
8 a 5.45 6.18 12.8 -4.92
9 b 5.43 18.2 9.55 27.3
10 b 4.16 12.1 4.11 23.5
Комментарии:
1. Ого! Так элегантно! Мне это нравится. Большое вам спасибо! 🙂
Ответ №2:
Базовый параметр R с использованием sweep
:
df1$new <- rowSums(sweep(df1[-1], 2, df2$q, `*`))
df1
# a b c d new
#1 a 7.171058 14.841556 8.448776 24.8645274
#2 a 7.418932 19.688917 3.972406 44.6793728
#3 a 5.781393 19.172166 9.659909 29.6862124
#4 a 5.093006 17.713560 12.769889 19.2671422
#5 a 7.211775 12.889949 6.239361 25.2314261
#6 a 2.364088 13.719159 2.502868 27.6588239
#7 a 7.260197 10.865697 10.664418 11.9859042
#8 a 5.447632 6.182824 12.780465 -4.9229877
#9 b 5.431681 18.187068 9.550564 27.2999847
#10 b 4.161356 12.090304 4.112985 23.4746295
#11 b 5.767504 15.949788 8.163847 25.8074686
#...
#...
Или другой вариант :
df1$new <- colSums(t(df1[-1]) * df2$q)
Убедитесь, что df2$p
они расположены в том же порядке, что и названия столбцов, или наоборот.
Комментарии:
1.
as.matrix(df1[df2$p]) %*% df2$q
2. @RonakShah Спасибо 🙂
Ответ №3:
В base R
мы можем использовать crossprod
df1$new <- crossprod(t(df1[-1]), df2$q)[,1]
head(df1)
# a b c d new
#1 a 7.171058 14.84156 8.448776 24.86453
#2 a 7.418932 19.68892 3.972406 44.67937
#3 a 5.781393 19.17217 9.659909 29.68621
#4 a 5.093006 17.71356 12.769889 19.26714
#5 a 7.211775 12.88995 6.239361 25.23143
#6 a 2.364088 13.71916 2.502868 27.65882