问题
I have a dataframe with some boolean values (1/0) as follows (sorry I couldn't work out how to make this into a smart table)
Flag1.Sam Flag2.Sam Flag3.Sam Flag1.Ted Flag2.Ted Flag3.Ted
probe1 0 1 0 1 0 0
probe2 0 0 0 0 0 0
probe3 1 0 0 0 0 0
probe4 0 0 0 0 0 0
probe5 1 1 0 1 0 0
I have 64 samples (Sam/Ted....etc) which are in a list called files i.e;
files <- c("Sam", "Ted", "Ann", ....)
And I would like to create a a column summing the flag values for each sample to create the following:
Sam Ted
probe1.flagsum 1 1
probe2.flagsum 0 0
probe3.flagsum 1 0
probe4.flagsum 0 0
probe5.flagsum 2 1
I am fairly new to R, trying to learn on a need to know basis but I have tried the following:
for(i in files) {
FLAGS$i <- cbind(sapply(i, function(y) {
#greping columns to filter for one sample
filter1 <- grep(names(filters), pattern=y)
#print out the summed values for those columns
FLAGS$y <-rowSums(filters[,(filter1)])
}
}
The above code does not work and I am bit lost as how to move forward.
Can anyone help me untangle this problem or point me in the right direction of the commands/tools to use.
Thank you.
回答1:
This is easily doable in base R reshape, though using the reshape or reshape2 packages might be more intuitive.
Here's a solution in base R:
# Here's your data in its current form
dat = read.table(header=TRUE, text="Flag1.Sam Flag2.Sam Flag3.Sam Flag1.Ted Flag2.Ted Flag3.Ted
probe1 0 1 0 1 0 0
probe2 0 0 0 0 0 0
probe3 1 0 0 0 0 0
probe4 0 0 0 0 0 0
probe5 1 1 0 1 0 0")
# Generate an ID row
dat$id = row.names(dat)
# Reshape wide to long
r.dat = reshape(dat, direction="long",
timevar="probe",
varying=1:6, sep=".")
# Calculate row sums
r.dat$sum = rowSums(r.dat[3:5])
# Reshape back to wide format, dropping what you're not interested in
reshape(r.dat, direction="wide",
idvar="id", timevar="probe",
drop=3:5)
## id sum.Sam sum.Ted
## probe1.Sam probe1 1 1
## probe2.Sam probe2 0 0
## probe3.Sam probe3 1 0
## probe4.Sam probe4 0 0
## probe5.Sam probe5 2 1
More than one way to skin a cat
You can also whip up a function like this one:
myFun = function(data, varnames) {
temp = vector("list", length(varnames))
for (i in 1:length(varnames)) {
temp[[i]] = colSums(t(dat[grep(varnames[i], names(data))]))
names(temp)[[i]] = varnames[i]
}
data.frame(temp)
}
Then, making use of the vector that you have of names:
files = c("Sam", "Ted")
myFun(dat, files)
## Sam Ted
## probe1 1 1
## probe2 0 0
## probe3 1 0
## probe4 0 0
## probe5 2 1
Enjoy!
回答2:
If filters is your input matrix and FLAGS your desired output matrix then I would (naïvely) do something like this:
FLAGS <- matrix(0,nrow=nrow(filters),ncol=length(files))
for(i in 1:length(files)){
grep(files[i],colnames(filters)) -> index
FLAGS[,i] <- rowSums(filters[,index])
}
colnames(FLAGS) <- files
回答3:
assuming your matrix is called input
input <- matrix(rbinom(30, 1, 0.5), ncol = 6)
colnames(input) <- c("F1.S", "F2.S", "F3.S", "F1.T", "F2.T", "F3.T")
rownames(input) <- paste("probe", 1:5, sep = "")
input <- as.data.frame(input)
library(reshape)
input$probe <- rownames(input)
Molten <- melt(input, id.vars = "probe")
Molten$ID <- gsub("^.*\\.", "", levels(Molten$variable))[Molten$variable]
cast(probe ~ ID, data = Molten, fun = "sum")
update with the dat frame from mrdwab
dat = read.table(header=TRUE, text="Flag1.Sam Flag2.Sam Flag3.Sam Flag1.Ted Flag2.Ted Flag3.Ted
probe1 0 1 0 1 0 0
probe2 0 0 0 0 0 0
probe3 1 0 0 0 0 0
probe4 0 0 0 0 0 0
probe5 1 1 0 1 0 0")
library(reshape)
dat$probe <- rownames(dat)
Molten <- melt(dat, id.vars = "probe")
Molten$ID <- gsub("^.*\\.", "", levels(Molten$variable))[Molten$variable]
cast(probe ~ ID, data = Molten, fun = "sum")
来源:https://stackoverflow.com/questions/11118384/loop-to-perform-calculations-across-rows-on-specific-columns-matching-a-pattern