Как создать вычисляемый столбец, используя таблицу поиска и формулу в R? - PullRequest
1 голос
/ 29 февраля 2020

У меня есть фрейм данных, который выглядит следующим образом:

   V1  V2   V3
   3    4   3
   2    4   3
   4    4   3
   4    4   4
   1    4   2
   4    2   4
   4    4   1
   4    4   2
   3    4   1
   4    4   4
   4    4   2
   4    4   2
   2    1   2
   3    2   3
   3    4   3
   3    4   2
   4    4   2
   4    4   4
   2    3   3
   3    4   1

У меня также есть таблица поиска вот так:

 V_id   coeff  weight 
  V1   0.82     4.77   
  V2   0.75     4.77   
  V3   0.67     4.77

Я хочу использовать эти значения в таблице поиска, чтобы создайте новый вычисляемый столбец в DF1, используя

(V1*coeff+V2*coeff+V3*coeff)/weight

Окончательный кадр данных должен выглядеть следующим образом.

   V1   V2  V3  new_column
   3    4   3   1.566037736
   2    4   3   1.394129979
   4    4   3   1.737945493
   4    4   4   1.878406709
   1    4   2   1.081761006
   4    2   4   1.5639413
   4    4   1   1.457023061
   4    4   2   1.597484277
   3    4   1   1.285115304
   4    4   4   1.878406709
   4    4   2   1.597484277
   4    4   2   1.597484277
   2    1   2   0.78197065
   3    2   3   1.251572327
   3    4   3   1.566037736
   3    4   2   1.42557652
   4    4   2   1.597484277
   4    4   4   1.878406709
   2    3   3   1.236897275
   3    4   1   1.285115304

Я должен сделать это для фрейма данных с 1125 столбцами.

Ответы [ 2 ]

1 голос
/ 29 февраля 2020

Редактировать Обновленный ответ на обновленный вопрос (фрейм данных имеет 1125 столбцов):

df1_V <- as.matrix(df1) # or select the "V" columns using df1[, 1:1125]
df1$new_column <- df1_V %*% df2$coef / df2$weight[1]

Это общее решение, которое будет работать для любого количества столбцов до тех пор, пока столбцы df1 упорядочены таким же образом (по столбцам фрейма данных), что и значения коэффициентов упорядочены (по строкам) в df2 , и количество столбцов в df1 равно количеству строк в df2 , то есть ncol(df1_V) = nrow(df2).


Ответ (на оригинальный вопрос):

library(dplyr)

df %>%
  mutate(new_column = (V1*0.82 + V2*0.75 + V3*0.67) / 4.77)

   V1 V2 V3 new_column
1   3  4  3  1.5660377
2   2  4  3  1.3941300
3   4  4  3  1.7379455
4   4  4  4  1.8784067
5   1  4  2  1.0817610
6   4  2  4  1.5639413
...

Альтернатива:

df1$new_column <- as.matrix(df1) %*% c(0.82, 0.75, 0.67) / 4.77
1 голос
/ 29 февраля 2020

Мы можем преобразовать первые данные в длинный формат, а затем выполнить группирование по номеру строки, чтобы получить вычисляемый столбец

library(dplyr)
library(tidyr)
df1 %>% 
   mutate(rn = row_number()) %>%
   pivot_longer(cols = -rn, names_to = "V_id") %>% 
   left_join(df2)  %>% 
   group_by(rn) %>% 
   summarise(new_column = sum(coeff *value)/weight[1]) %>% 
   select(new_column) %>% 
   bind_cols(df1, .)
# A tibble: 20 x 4
#      V1    V2    V3 new_column
#   <int> <int> <int>      <dbl>
# 1     3     4     3      1.57 
# 2     2     4     3      1.39 
# 3     4     4     3      1.74 
# 4     4     4     4      1.88 
# 5     1     4     2      1.08 
# 6     4     2     4      1.56 
# 7     4     4     1      1.46 
# 8     4     4     2      1.60 
# 9     3     4     1      1.29 
#10     4     4     4      1.88 
#11     4     4     2      1.60 
#12     4     4     2      1.60 
#13     2     1     2      0.782
#14     3     2     3      1.25 
#15     3     4     3      1.57 
#16     3     4     2      1.43 
#17     4     4     2      1.60 
#18     4     4     4      1.88 
#19     2     3     3      1.24 
#20     3     4     1      1.29 

В base R мы также можем сделать

df1$new_column <- c(tcrossprod(df2$coeff, as.matrix(df1)))/df2$weight[1]

данные

df1 <- structure(list(V1 = c(3L, 2L, 4L, 4L, 1L, 4L, 4L, 4L, 3L, 4L, 
4L, 4L, 2L, 3L, 3L, 3L, 4L, 4L, 2L, 3L), V2 = c(4L, 4L, 4L, 4L, 
4L, 2L, 4L, 4L, 4L, 4L, 4L, 4L, 1L, 2L, 4L, 4L, 4L, 4L, 3L, 4L
), V3 = c(3L, 3L, 3L, 4L, 2L, 4L, 1L, 2L, 1L, 4L, 2L, 2L, 2L, 
3L, 3L, 2L, 2L, 4L, 3L, 1L)), class = "data.frame", row.names = c(NA, 
-20L))

df2 <- structure(list(V_id = c("V1", "V2", "V3"), coeff = c(0.82, 0.75, 
0.67), weight = c(4.77, 4.77, 4.77)), class = "data.frame", row.names = c(NA, 
-3L))
...