#r #mapply
#r #mapply
Вопрос:
У меня есть фрейм данных, подобный этому:
df <- data.frame(size_upms = c(126, 123, 148),
electric_mean = c(0.716756756756757,0.647859922178988, 0.726313694267516),
gas_mean = c(0.273513513513513,0.322679266259033, 0.259554140127389),
firewood_mean = c(0, 0.00111172873818788,0.00179140127388535))
# df
# size_upms electric_mean gas_mean firewood_mean
#1 126 0.7167568 0.2735135 0.000000000
#2 123 0.6478599 0.3226793 0.001111729
#3 148 0.7263137 0.2595541 0.001791401
Я хочу получить образцы, используя параметры для каждой строки, используя mapply
l <- mapply(sample,c("electric","gas","firewood"),df$size_upms,TRUE,
c(df$electric_mean,df$gas_mean,df$firewood_mean))
Но я получаю эту ошибку:
#Error in sample.int(length(x), size, replace, prob) :
# too few positive probabilities
Однако, если я применяю функцию sample к каждой строке, это работает:
sample(c("electric","gas","firewood"),df$size_upms[1],TRUE,
c(df$electric_mean[1],df$gas_mean[1],df$firewood_mean[1]))[1:5]
#[1] "gas" "electric" "electric" "gas" "electric"
sample(c("electric","gas","firewood"),df$size_upms[2],TRUE,
c(df$electric_mean[2],df$gas_mean[1],df$firewood_mean[2]))[1:5]
#[1] "electric" "gas" "gas" "gas" "electric"
sample(c("electric","gas","firewood"),df$size_upms[3],TRUE,
c(df$electric_mean[3],df$gas_mean[3],df$firewood_mean[1]))[1:5]
#[1] "electric" "electric" "gas" "electric" "electric"
Но я хочу использовать mapply, потому что я хочу применить его к большому фрейму данных
Что я делаю не так?
Ответ №1:
Поскольку это выполняется по строкам, это проще сделать с помощью apply
или lapply
. Между mapply
или другими apply
решениями не будет большой разницы в производительности
lapply(seq_len(nrow(df)), function(i)
sample(c("electric","gas","firewood"), df$size_upms[i], TRUE,
unlist(c(df$electric_mean[i],df$gas_mean[i],df$firewood_mean[i]))))
Ошибка в решении OP — это процесс конкатенации. Здесь мы передаем аргументы в виде отдельных столбцов из набора данных, а затем в анонимном вызове функции выполняем конкатенацию. Это позволит убедиться, что для каждого шага выбран соответствующий элемент строки из столбца.
Map(function(x,y, u, w) sample(c("electric","gas","firewood"), x,
TRUE, c(y, u, w)), df$size_upms, df$electric_mean, df$gas_mean, df$firewood_mean)
Или, как прокомментировал @thelatemail, мы можем избежать некоторого ввода, используя do.call
do.call(Map, c( function(x,y, u, w)
sample(c("electric","gas","firewood"), x, TRUE, c(y,u,w)), unname(df)))
Комментарии:
1.
Map
Решение, на мой взгляд, самое аккуратное.2. Вы могли бы даже немного сэкономить на вводе, например
do.call(Map, c( function(x,y, u, w) sample(c("electric","gas","firewood"), x, TRUE, c(y,u,w)), unname(df) ))
3. Потрясающе, спасибо за очень подробное объяснение @akrun
4. @Israel, аргументы анонимного вызова функции соответствуют каждому из входных аргументов в Map. т.е. ‘x’ будет ‘df $ size_upms’
5. Большое спасибо @akrun