Используйте ddply() для агрегации относительного количества гистограмм
В связи с предыдущим вопросом, который я задал ( ggplot2, как получить 2 гистограммы со значением y = для подсчета одного / суммы подсчета обоих), я попытался написать функцию, которая бы принимала data.frame в качестве входных данных с ответом время (RT) и точность (правильность) нескольких участников в нескольких условиях, и выводит "итоговый" data.frame с данными, агрегированными, как в гистограмме. Специфика здесь в том, что я не хочу получать абсолютное количество ответов в каждом бине, а относительное количество.
Относительный счет я называю тем, что для каждого бина гистограммы значение соответствует:
relative_correct = ncorrect / sum(ncorrect+nincorrect)
relative_incorrect = nincorrect / sum(ncorrect+nincorrect)
Результат фактически близок к графику плотности, за исключением того, что это не сумма каждой кривой, равной 1, а сумма правильных и неправильных кривых.
Вот код для создания примера данных:
# CREATE EXAMPLE DATA
subjectname <- factor(rep(c("obs1","obs2"),each=50))
Visibility <- factor(rep(rep(c("cond1","cond2"),each=25),2))
RT <- rnorm(100,300,50)
correct <- sample(c(rep(0,25),rep(1,75)),100)
my.data <- data.frame(subjectname,Visibility,RT,correct)
Сначала мне нужно определить функцию для последующего использования в ddply
histRTcounts <- function(df) {out = hist(df$RT, breaks=seq(5, 800, by=10), plot=FALSE)
out = out$counts}
И затем основная функция (есть 2 небольших проблемы, которые мешают ей работать как внутри функции, смотрите строки с?????, но вне функции этот код работает).
relative_hist_count <- function(df, myfactors) {
require(ggplot2)
require(plyr)
require(reshape2)
# ddply it to get one column for each bin of the histogram
myhistRTcounts <- ddply(df, c(myfactors,"correct"), histRTcounts)
# transform it in long format
myhistRTcounts.long = melt(myhistRTcounts, id.vars =c(myfactors,"correct"), variable.name="bin", value.name = 'mycount')
# rename the bin names with the ms value they correspond to
levels(myhistRTcounts.long$bin) <- seq(5, 800, by=10)[-1]-5
# make them numeric and not a factor anymore
myhistRTcounts.long$bin = as.numeric(levels(myhistRTcounts.long$bin))[myhistRTcounts.long$bin]
# cast to have count_correct and count_incorrect as columns
# ??????????????????????? problem when putting that into a function
# Here I was not able to figure out how to combine myfactors to the other variables in the call
myhistRTcount.short = dcast(myhistRTcounts.long, subjectname + Visibility + bin ~ correct)
names(myhistRTcount.short)[4:5] <- c("countinc","countcor")
# compute relative counts
myhistRTcounts.rel <- ddply(myhistRTcount.short, myfactors, transform,
incorrect = countinc / sum(countinc+countcor),
correct = countcor / sum(countinc+countcor)
)
myhistRTcounts.rel = subset(myhistRTcounts.rel,select=c(-countinc,-countcor))
myhistRTcounts.rel.long = melt(myhistRTcounts.rel, id.vars = c(myfactors,"bin"), variable.name = 'correct', value.name = 'mycount')
# ??????????????????????? idem here, problem when putting that into a function to call myfactors
ggplot(data=myhistRTcounts.rel.long, aes(x=bin, y=mycount, color=factor(correct))) + geom_line() + facet_grid(Visibility ~ subjectname) + xlim(0, 600) + theme_bw()
return(myhistRTcounts.rel.long)
Призыв применить его к данным
new.df = relative_hist_count(my.data, myfactors = c("subjectname","Visibility"))
Итак, во-первых, мне нужна ваша помощь, чтобы заставить это работать как функцию с возможностью использования переменной myfactors в dcast() и ggplot().
Но что еще более важно, я почти уверен, что эта функция может быть написана гораздо более элегантно и простым способом, с меньшим количеством шагов.
Заранее спасибо за вашу помощь!
2 ответа
Спасибо Роланд, я не думал о написании самодельной функции истории. Пожалуйста, найдите это ниже:
RelativeHistRT <- function (df, breaks = seq(5,800,10))
{
distrib.correct = hist(df$RT[df$correct==1], breaks, right=FALSE, plot=FALSE)
distrib.incorrect = hist(df$RT[df$correct==0], breaks, right=FALSE, plot=FALSE)
n.total = sum(distrib.correct$counts) + sum(distrib.incorrect$counts)
data.frame(bin_mids = distrib.correct$mids,
correct = distrib.correct$counts / n.total,
incorrect = distrib.incorrect$counts / n.total)
}
И применить его к моему оригинальному data.frame и получить то, что я искал:
myhistRTcounts <- ddply(my.data, .(subjectname,Visibility), RelativeHistRT)
Это действительно намного короче и делает именно то, что я искал.
Может быть, это помогает с настройкой данных?
countfun <- function(x,...) {
res <- hist(x,plot=FALSE,...)
data.frame(counts=res$counts,
break1=res$breaks[-length(res$breaks)],
break2=res$breaks[-1])
}
library(plyr)
plot.dat <- ddply(my.data,.(Visibility),function(df){
res <- ddply(df,.(correct),function(df2) {countfun(df2$RT,breaks=seq(100, 600, by=10))})
res$freq2 <- res$counts/nrow(df)
res
})
Вам, вероятно, нужно целое parse
, eval
, as.formula
материал для обобщения на произвольные факторы. У меня сейчас нет на это времени.
Однако, если вы планируете обобщить, было бы лучше изменить hist
функция для принятия параметра для использования в качестве фактора на счетчиках.