This question is similar to a previous one I made here: randomly sum values from rows and assign them to 2 columns in R
Since I'm having difficulties with R, this question is both about programming and statistics. I'm very new to both.
I have a data.frame with 219 subjects in one column. The rest of the columns are 7, and in each row I have a number which represents a difference in response time for that particular subject when exposed to the two conditions of the experiment.
This is how the data looks (I'm using the head function, otherwise it would be too long):
> head(RTsdiff)
subject block3diff block4diff block5diff block6diff block7diff
1 40002 0.076961798 0.046067460 -0.027012048 0.017920261 0.002660317
2 40004 0.037558511 -0.016535211 -0.044306743 -0.011541667 0.044422892
3 40006 -0.017063123 -0.031156150 -0.084003876 -0.070227149 -0.113382784
4 40008 -0.015204017 -0.009954545 -0.004082353 0.006327839 0.022335271
5 40009 0.006055829 -0.045376437 -0.002725572 0.016443182 0.032848128
6 40010 -0.003017857 -0.034398268 -0.034476491 0.014158824 -0.036592982
block8diff block9dif
1 0.03652273 0.037306173
2 -0.08032784 -0.150682051
3 -0.09724864 -0.060338684
4 -0.04783333 0.006539326
5 -0.01459465 -0.067916667
6 -0.01868126 -0.034409584
What I need is a code that will, for every subject (i.e. every row) will sample either 3 or 4 values, average them, and add them to a new vector (called half1). The vector half2 should have the average of the values that were not sampled in the first try.
So, supposing the data.frame I want t create was called "RTshalves", I would need the first column to be the same column of subjects in RTsdiff, the second column must have in the first row the average of the randomly selected values that correspond to the first subject, and the second column must have the average of the values of the first subject that were not chosen in the first sampling. The second row of columns 2 and 3 should have the same information, but this time for subject 2 (that is subject 40004 in my data.frame), etc, until reaching the 219 subjects.
Let's suppose that the first sample randomly selected 3 values of subject 1 (block3diff, block5diff and block9diff) and thus the values of block4diff, block6diff, block7diff and block8diff would automatically correspond to the other half. Then, what I would expect to see (considering only the first of the 219 rows) is:
Subject Half1 Half2
40002 0.02908531 0.02579269
If anyone is interested in the statistics behind this, I'm trying to do a split-half reliability test to check for the consistency of a test. The rationale is that if the difference in RT average is a reliable estimator of the effect, then the differences of half of the blocks of one participant should be correlated to the differences of the other half of the blocks.
Help is much appreciated. Thanks in advance.
half1 is easy: write your own function to do what you want to each row (taken in as a vector), then apply
it to the rows:
eachrow <- function(x) {
mean(sample(x,2))
}
RTsdiff$half1 <- apply(eachrow,1,RTsdiff)
To get half2, you'll probably want to do it at the same time. ddply
might be easiest for this (let the by argument be your subject variable to get each row). Like this:
RTsdiff <- data.frame(subject=seq(6))
RTsdiff <- cbind( RTsdiff, matrix(runif(6*8),ncol=8) )
library(plyr)
eachrow <- function(x,n=3) {
x <- as.numeric(x[,2:ncol(x)]) # eliminate the ID column to make things easier, make a vector
s <- seq(length(x))
ones <- sample(s,n) # get ids for half1
twos <- !(s %in% ones) # get ids for half2
data.frame( half1=mean(x[ones]), half2=mean(x[twos]) )
}
ddply( RTsdiff, .(subject), eachrow)
subject half1 half2
1 1 0.4700982 0.5350610
2 2 0.6173469 0.5351995
3 3 0.2245246 0.6807482
4 4 0.6330649 0.6316353
5 5 0.6388060 0.6629077
6 6 0.4652086 0.5073034
There are plenty of more elegant ways of doing this. In particular, I used ddply
for its ability to easily output data.frames so that I could output both half1
and half2
from the function and have them combined up nicely at the end, but ddply
takes data.frames as input, so there's some slight machination to get it out to a vector first. Feeding sapply
a transposed data.frame would possibly be simpler.