免责声明:我是R和大数据新手;我对Python相当不错,但我对操作大数据的经验不多,并且不知道常用的R方法来做我认为应该是相当常见的任务。
我有一组来自实验的数据(在数据框中),每个样本都是一式两份运行的。标题看起来像这样:
> foo.sampledata[1:3,1:5]
uniq.id jb_229.002_2 jb_229.002_1 jb_229.006_2 jb_229.006_1
1 400.2787_44.47 0 0 0 5629
2 406.2713_72.81 0 7451 16315 0
3 406.5656_41.37 0 0 0 0
每列有40列样本数据和约26,000行。
我想要做的是为每对列中的每一行取每个样本的两次运行(例如上面的jb_229.002_2
和jb_229.002_1
)的平均值,然后将其存储在一个新的列下专栏命名为jb_229.002
。
我在(较小的)测试数据集上使用的解决方案来自另一个stackoverflow问题(https://stackoverflow.com/a/12397402):
foo.means <- ddply(foo.sampledata, .(uniq.id), function(x) {
foo <- melt(x, id.vars = 1)
foo$variable <- substr(foo$variable, 1, 10)
return(dcast(foo, uniq.id ~ variable, mean))})
这适用于我较小的测试集但是占用了我所有的RAM并且当我尝试使用全套时基本上崩溃R.我理解为什么这么长时间 - 它创造了两次巨大的新表 - 但我不知道另一种方法。
任何建议/资源/范例/公众羞辱都赞赏!
答案 0 :(得分:2)
如果您的示例具有代表性,您可以执行此操作,对于如此少量的列,它应该非常快:
DF <- read.table(text = " uniq.id jb_229.002_2 jb_229.002_1 jb_229.006_2 jb_229.006_1
1 400.2787_44.47 0 0 0 5629
2 406.2713_72.81 0 7451 16315 0
3 406.5656_41.37 0 0 0 0")
#make sure duplicates are in right order
DF <- DF[, c(1, order(names(DF)[-1])+ 1)]
#loop over column pairs
res <- cbind(DF[, 1, drop = FALSE],
sapply(seq_len((ncol(DF) - 1) %/% 2), function(i, DF) {
n1 <- substring(names(DF)[2 * i], 1, nchar(names(DF)[2 * i]) - 2)
n2 <- substring(names(DF)[2 * i - 1], 1, nchar(names(DF)[2 * i]) - 2)
stopifnot(n1 == n2)
setNames(data.frame((DF[, 2 * i] + DF[, 2 * i - 1]) / 2),
n1)
}, DF = DF[, -1]))
# uniq.id jb_229.002 jb_229.006
#1 400.2787_44.47 0.0 2814.5
#2 406.2713_72.81 3725.5 8157.5
#3 406.5656_41.37 0.0 0.0
请注意,(DF[,1] + DF[,2]) / 2
通常比rowMeans(DF[, 1:2])
更快。
答案 1 :(得分:1)
这是一个部分答案,我认为在基础R中可能会有所帮助。
uniq.id jb_229.002 jb_229.006
1 400.2787_44.47 0 5629
2 406.2713_72.81 7451 16315
3 406.5656_41.37 0 0
返回
setNames(data.frame(df[1],
lapply(myCols,
function(i) rowMeans(df[, grep(i, names(df))]))),
c(names(df)[1], myCols))
现在,计算方法可能更容易。
如果目标是计算每行对的平均值,那么您可以在评论中使用rowMeans作为@roland指出,如下所示:
uniq.id jb_229.002 jb_229.006
1 400.2787_44.47 0.0 2814.5
2 406.2713_72.81 3725.5 8157.5
3 406.5656_41.37 0.0 0.0
返回
xlApp = new Excel.Application();
xlWorkBook = xlApp.Workbooks.Add(misValue);
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
xlWorkSheet = (Microsoft.Office.Interop.Excel.Worksheet)xlWorkBook.Worksheets.Add(System.Reflection.Missing.Value, xlWorkBook.Worksheets[xlWorkBook.Worksheets.Count], System.Reflection.Missing.Value, System.Reflection.Missing.Value);
xlWorkSheet.Name = "Added through code";
答案 2 :(得分:1)
感谢所有人的答案 - 他们既简洁又精心设计。我浏览了data.table
个小插图并使用该数据类型执行此操作,如下所示:
# Truncate names so jb_229-002_2 and jb_229-002_1 are both jb_229-001
setnames(foo,substring(names(foo),1,10))
# Stack every other column
foo.c = rbind(foo[,c(1,seq(2,ncol(foo),by=2)),with=FALSE],
foo[,c(1,seq(3,ncol(foo),by=2)),with=FALSE])
# for each uid, calculate the mean of each column of the subset.
foo.means = foo.c[ , lapply(.SD, mean), by=uniq.id ]
其他答案实际上更好地解决了我关于以编程方式匹配列名称的问题 - 我只是通过在rbind
中交替列来解决这个问题。帮我一个忙,不要告诉任何人。
再次感谢所有人!