В функции R: dcast in передать имена столбцов (снова!)

Дан df в полудлинном формате с идентификаторами переменных a и b и измеренными данными в столбцах m1и m2. Тип данных задается переменной v (значения var1 и var2).

set.seed(8)

df_l <- 
  data.frame(
    a = rep(sample(LETTERS,5),2),
    b = rep(sample(letters,5),2),
    v = c(rep("var1",5),rep("var2",5)),
    m1 = sample(1:10,10,F),
    m2 = sample(20:40,10,F)) 

Выглядит как:

   a b    v m1 m2
1  W r var1  3 40
2  N l var1  6 32
3  R a var1  9 28
4  F g var1  5 21
5  E u var1  4 38
6  W r var2  1 35
7  N l var2  8 33
8  R a var2 10 29
9  F g var2  7 30
10 E u var2  2 23

Если я хочу сделать широкий формат значений в m1, используя идентификатор a в качестве строк и значений в столбцах v1as, я делаю:

> reshape2::dcast(df_l, a~v, value.var="m1")
  a var1 var2
1 E    4    2
2 F    5    7
3 N    6    8
4 R    9   10
5 W    3    1

Как мне написать функцию, которая делает это, если аргументы для dcast (строка, столбец и значение.var) предоставляются в качестве аргументов, что-то вроде:

fun <- function(df,row,col,val){
  require(reshape2)
  res <-
    dcast(df, row~col, value.var=val)
  return(res)
}

Я проверил SO здесь и здесь попробовать варианты match.call и eval(substitute()), чтобы "получить" аргументы внутри функции, а также пробовал с пакетом lazyeval. Нет успеха.

Что я здесь делаю неправильно? Как заставить dcast распознавать имена переменных?


person user3375672    schedule 08.07.2015    source источник


Ответы (1)


Аргумент формулы также принимает ввод символов.

foo <- function(df, id, measure, val) {
    dcast(df, paste(paste(id, collapse = " + "), "~", 
                    paste(measure, collapse = " + ")), 
          value.var = val)
}

require(reshape2)
foo(df_l, "a", "v", "m1")

Обратите внимание, что dcast data.table (текущая разработка) также может напрямую приводить несколько столбцов value.var. Итак, вы также можете сделать:

require(data.table) # v1.9.5
foo(setDT(df_l), "a", "v", c("m1", "m2"))
#    a m1_var1 m1_var2 m2_var1 m2_var2
# 1: F       1       6      28      21
# 2: H       9       2      38      29
# 3: M       5      10      24      35
# 4: O       8       3      23      26
# 5: T       4       7      31      39
person Arun    schedule 08.07.2015
comment
Два очень хороших ответа - я буду дальше разжевывать функцию setDT, она кажется ужасно полезной. - person user3375672; 08.07.2015
comment
Сбоку: почему моя строка не работает: dcast(df, row~col, value.var=val)? - person user3375672; 08.07.2015
comment
Сообщение об ошибке от reshape2::dcast довольно загадочно. Это потому, что row ~ col приводит к тому, что dcast ищет столбцы с именами row и col в вашем df. Установите версию dt для разработки, загрузите ее и запустите dcast(setDT(df), row ~ col, value.var="m1"), и сообщение об ошибке должно быть совершенно ясным. - person Arun; 08.07.2015
comment
вариант с несколькими переменными действительно полезен! - person JelenaČuklina; 10.05.2018