Как создать функцию, которая перебирает индексные номера столбцов в R? - PullRequest
1 голос
/ 25 апреля 2019

Рассмотрим следующий кадр данных (df):

"id"   "a1"   "b1"   "c1"   "not_relevant"   "p_a1"   "p_b1"   "p_c1"
 a      2      6      0           x             2        19       12
 a      4      2      7           x           3.5         7       11
 b      1      9      4           x             7       1.5        4
 b      7      5      11          x             8        12        5

Я хотел бы создать новый столбец, который показывает сумму произведений между двумя соответствующими столбцами. Чтобы написать меньше кода, я адресую столбцы по их индексу. К сожалению, у меня нет опыта написания функций, поэтому я сделал это вручную, что крайне утомительно и не очень элегантно.

Вот воспроизводимый пример фрейма данных и того, что я пробовал до сих пор:

id <- c("a","a","b","b")
df <- data.frame(id)
df$a1 <- as.numeric((c(2,4,1,7)))
df$b1 <- as.numeric((c(6,2,9,5)))
df$c1 <- as.numeric((c(0,7,4,11)))
df$not_relevant <- c("x","x","x","x")
df$p_a1 <- as.numeric((c(2,3.5,7,8)))
df$p_b1 <- as.numeric((c(19,7,1.5,12)))
df$p_c1 <- as.numeric((c(12,11,4,5)))

require(dplyr)

df %>% mutate(total = .[[2]]*.[[6]] + .[[3]] *.[[7]]+ .[[4]] *.[[8]])

Это приводит к желаемому результату, но, как я уже говорил, не очень эффективно:

"id"   "a1"   "b1"   "c1"   "not_relevant"   "p_a1"   "p_b1"   "p_c1"   "total"
 a      2      6      0           x             2        19       12     118.0
 a      4      2      7           x           3.5         7       11     105.0
 b      1      9      4           x             7       1.5        4      36.5
 b      7      5      11          x             8        12        5     171.0

Реальные данные, с которыми я работаю, имеют гораздо больше столбцов, поэтому я был бы рад, если бы кто-нибудь показал мне способ упаковать эту операцию в функцию, которая перебирает порядковые номера столбцов и сопоставляет правильные столбцы друг с другом.

1 Ответ

1 голос
/ 25 апреля 2019

Индексы столбцов не являются хорошим способом сделать это.(В общем, не очень хороший способ ...)

Вот простой dplyr метод, который предполагает, что столбцы находятся в правильном соответствующем порядке (то есть он даст неверный результат, если "x1", "x2", "x3"в другом порядке, чем "p_x3", "p_x2", "p_x1").Вам также может понадобиться уточнить критерии выбора для ваших реальных данных:

df$total = rowSums(select(df, starts_with("x")) * select(df, starts_with("p_")))
df
#   id x1 x2 x3 not_relevant p_x1 p_x2 p_x3 total
# 1  a  2  6  0            x  2.0 19.0   12 118.0
# 2  a  4  2  7            x  3.5  7.0   11 105.0
# 3  b  1  9  4            x  7.0  1.5    4  36.5
# 4  b  7  5 11            x  8.0 12.0    5 171.0

Другим хорошим вариантом будет преобразование ваших данных в длинный формат, где у вас есть один столбец x и одинСтолбец p, в столбце «index» указываются значения 1, 2, 3. Затем операция может быть выполнена по группам, наконец, возвращаясь к широкому формату.

...