采用基于列名的数据框列

时间:2017-02-10 15:20:17

标签: r bigdata

免责声明:我是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_2jb_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.我理解为什么这么长时间 - 它创造了两次巨大的新表 - 但我不知道另一种方法。

任何建议/资源/范例/公众羞辱都赞赏!

3 个答案:

答案 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中交替列来解决这个问题。帮我一个忙,不要告诉任何人。

再次感谢所有人!