R 采用基于列名的数据帧列方式

R 采用基于列名的数据帧列方式,r,bigdata,R,Bigdata,免责声明:我是一个网络和大数据新手;我对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

免责声明:我是一个网络和大数据新手;我对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
setNames(data.frame(df[1],
                   lapply(myCols,
                          function(i) rowMeans(df[, grep(i, names(df))]))),
         c(names(df)[1], myCols))
样本数据有40列,每列大约26000行

我想做的是,为每对列中的每一行获取每个样本的两次运行的平均值,例如上面的jb_229.002_2和jb_229.002_1,然后将其存储在名为jb_229.002的新列下

我在较小的测试数据集上使用的解决方案来自另一个stackoverflow问题:

这在我较小的测试集上运行得很好,但占用了我所有的RAM,当我尝试使用完整的测试集时,基本上会使R崩溃。我理解为什么要花这么长时间——要创建两个巨大的新表——但我不知道其他方法


任何建议/资源/例子/公众羞辱都将不胜感激

这里有一个部分答案,我认为这可能对base R有所帮助

# get unique names of trial variables
myCols <- unique(substr(names(df[-1]), 1, nchar(names(df[-1]))-2))
# construct a data.frame that combines the trials into a single column
setNames(data.frame(df[1],
                   lapply(myCols, function(i) rowSums(df[, grep(i, names(df))]))),
         c(names(df)[1], myCols))
现在,计算平均值可能更容易

如果目标是计算每行对的平均值,那么您可以使用@roland在注释中指出的rowMeans,如下所示:

> 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
setNames(data.frame(df[1],
                   lapply(myCols,
                          function(i) rowMeans(df[, grep(i, names(df))]))),
         c(names(df)[1], myCols))
返回

         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
         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

这里有一个部分答案,我认为这可能对BaseR有所帮助

# get unique names of trial variables
myCols <- unique(substr(names(df[-1]), 1, nchar(names(df[-1]))-2))
# construct a data.frame that combines the trials into a single column
setNames(data.frame(df[1],
                   lapply(myCols, function(i) rowSums(df[, grep(i, names(df))]))),
         c(names(df)[1], myCols))
现在,计算平均值可能更容易

如果目标是计算每行对的平均值,那么您可以使用@roland在注释中指出的rowMeans,如下所示:

> 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
setNames(data.frame(df[1],
                   lapply(myCols,
                          function(i) rowMeans(df[, grep(i, names(df))]))),
         c(names(df)[1], myCols))
返回

         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
         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 <- 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通常比rowMeansDF[,1: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通常比rowMeansDF[,1:2]快。

谢谢大家的回答,他们都很简洁,设计也很好。我浏览了data.table vignettes,并使用该数据类型完成了以下操作:

# 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中交替列来有点笨拙。帮我个忙,别告诉任何人


再次感谢大家

谢谢大家的回答,它们既简洁又精心设计。我浏览了data.table vignettes,并使用该数据类型完成了以下操作:

# 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中交替列来有点笨拙。帮我个忙,别告诉任何人


再次感谢大家

如果你对艾伦的评论是这样的,你可以通过阅读这些小插曲找到数据的例子。表格:我建议按顺序阅读它们。谢谢弗兰克,我会查出来的。还有一些关于你是如何理解公众羞辱的内部消息肯定会有帮助:嘿,好吧,我已经在这里呆了很长时间了,我知道如果你问问题时没有首先对TFM进行完整的研究,你可能应该得到一点;aa而且你现在有了更多的尊重:如果你对艾伦的评论是,你可以找到数据的例子。通过阅读小插曲表:我建议按顺序阅读。谢谢弗兰克,我会检查一下。还有一些关于你如何理解公众羞辱的内部消息肯定会有帮助:呵呵,我已经在这里呆了很长时间了,我知道如果你问问题时没有首先对TFM进行完整的研究,你可能应该得到一点;aa您现在有了更多的尊重: