as.formula не любит эквивалентность '=' (объект не найден)

рассмотрим следующий пример

df1 <- data.frame(a=c(1,2,3),b=c(2,4,6));
transform(df1,c=a+b)
    a b c
  1 1 2 3
  2 2 4 6
  3 3 6 9

Все идет нормально. Теперь я хотел бы закодировать это динамически, используя as.formula:

transform(df1,as.formula("c=a+b"))

Однако Р говорит

Error in eval(expr, envir, enclos) : object 'b' not found

Эта ошибка не возникает при использовании «~» в качестве разделителя левой и правой сторон. Можно ли как-то задержать оценку формулы? Можно ли вообще использовать as.formula в задании? Я пытался возиться с «с», но безрезультатно.


person Johannes    schedule 01.02.2012    source источник
comment
Я думаю, вы хотите, чтобы они были expression, а не формулами. Тем не менее, похоже, что в конечном итоге вы получите какую-то вариацию eval(parse(text="whatever")), что приведет к ужасному, ужасному коду и трудным для поиска ошибкам. Если возможно, попробуйте сделать что-нибудь менее умное.   -  person Richie Cotton    schedule 01.02.2012
comment
Было бы лучше разделить строку символов на знак равенства. Слева можно так что-то вроде df1[["c"]] <- something. Переход от "a+b" к оценке в df1 означает eval(parse(text = "a+b"), df1) или что-то столь же уродливое. Я предлагаю вам рассказать нам больше о том, чего вы пытаетесь достичь, чтобы мы могли помочь придумать альтернативу.   -  person Richie Cotton    schedule 01.02.2012
comment
В моей реальной проблеме не обязательно делать это автоматически. У меня всего около 50 столбцов с именами, попадающими в категорию X[XOY][ABC]_[0-9][0-9], например XXA_05. Теперь я хотел бы усреднить все столбцы одного и того же типа X [XOY] и одинаковых цифр, например XXA_00 и XXB_00, и сохранить их в первом из этих столбцов. Это, конечно, также можно сделать на уровне столбца, выбрав нужные столбцы. Я только что наткнулся на проблему формулы и хочу знать, возможно ли вообще реализовать ее как формулу.   -  person Johannes    schedule 01.02.2012
comment
Не используйте преобразование. Это вспомогательная функция, подходящая для интерактивного использования, а не для программирования.   -  person hadley    schedule 01.02.2012
comment
Не могли бы вы уточнить? Так что я должен использовать, например, df[[col1]]‹-df[[col2]]+df[[col3]] вместо преобразования?   -  person Johannes    schedule 01.02.2012
comment
Также обратите внимание на предупреждение в файле справки: если некоторые из значений не являются векторами соответствующей длины, вы заслуживаете того, что получите!   -  person James    schedule 01.02.2012


Ответы (1)


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

Воспроизводимая версия вашего набора данных.

group_names <- apply(
    expand.grid("X", c("X", "O", "Y"), c("A", "B", "C"), "_", 0:9, 0:9),
    1,
    paste,
    collapse = ""
)
n_groups <- 50
n_points_per_group <- 10
df1 <- as.data.frame(matrix(
    runif(n_points_per_group * n_groups),
    ncol = n_groups
))
colnames(df1) <- sample(group_names, n_groups)

Теперь преобразуйте фрейм данных в длинный формат. (Здесь используется пакет reshape. Вы также можете использовать stats::reshape.)

melted_df1 <- melt(df1)

Определите группу на основе ваших критериев совпадения второго символа и числа.

melted_df1$group <- with(melted_df1, paste(
    substring(variable, 2, 2),    
    substring(variable, 5, 6),
    sep = ""
))

Теперь позвоните tapply (или plyr::ddply, если хотите), чтобы получить сводную статистику.

with(melted_df1, tapply(value, group, mean))
person Richie Cotton    schedule 01.02.2012