r - lapply 将一列除以来自不同数据集的整数值,意外结果
r - lapply divides a column by an integer value from different dataset, unexpected result
我有两个 data.frames,一个有基因型计数,一个有一个数字,我需要从第一个数据集中对我的计数进行标准化。
countsdata=data.frame(genotype1=rep(c(10,20,30,40),each=1),
genotype2=rep(c(100,200,300,400),each=1),
genotype3=rep(c(40,50,60,70),each=1),
genotype4=rep(c(40,50,60,70),each=1)
)
coldata = data.frame(Group =c('genotype1', 'genotype2', 'genotype3', 'genotype4'),
Treatment = rep(c("control","treated"),each = 2),
Norm=rep(c(1,2,5,5)))
我确保我的变量没有因子
factorsCharacter <- function(d) modifyList(d, lapply(d[, sapply(d, is.factor)],
as.character))
coldata=factorsCharacter(coldata)
然后我看到 lapply 循环遍历我的计数,每次一列,并遍历包含归一化值 (Norm) 的 coldata。一切看起来都很好,直到我在同一步骤中组合了两个动作
> lapply(coldata['Group'],function(group_i){group_i})
$Group
[1] "genotype1" "genotype2" "genotype3" "genotype4"
> lapply(coldata['Group'],function(group_i){countsdata[,group_i]})
$Group
genotype1 genotype2 genotype3 genotype4
1 10 100 40 40
2 20 200 50 50
3 30 300 60 60
4 40 400 70 70
> lapply(coldata['Group'],function(group_i){as.integer(coldata[coldata$Group==group_i,'Norm'])})
$Group
[1] 1 2 5 5
> lapply(coldata['Group'],function(group_i){
+ countsdata[,group_i]/as.integer(coldata[coldata$Group==group_i,'Norm'])
+ })
$Group
genotype1 genotype2 genotype3 genotype4
1 10 100 40 40
2 10 100 25 25
3 6 60 12 12
4 8 80 14 14
这里的结果不是我所期望的(将每列除以其归一化数)。进一步检查后,我注意到它是按行规范化的,换句话说,它是跨不同列规范化的,这不应该是这种情况,因为我当时正在循环浏览一列。我可能遗漏了一个基本概念,但浏览其他 SO 帖子没有找到任何我可以使用的东西。我的目标是修复代码以进行正确的计算,但我也想了解为什么上面的代码不起作用。非常感谢。
问题在于使用 [
而不是 [[
。因此,我们没有遍历 'Group' 列中的每个元素,而是有一个包含所有元素的长度为 1 的 list
。因此,使用 coldata[, 'Group']
或 coldata[['Group']]
或 coldata$Group
进行循环。
countsdataNew <- countsdata
countsdataNew[] <- lapply(coldata[['Group']],function(group_i)
countsdata[,group_i]/coldata$Norm[coldata$Group==group_i])
countsdataNew
# genotype1 genotype2 genotype3 genotype4
#1 10 50 8 8
#2 20 100 10 10
#3 30 150 12 12
#4 40 200 14 14
如果 'countsdata' 中的列名和 'countsdata' 中的 'Group' 列的顺序相同,我们可以使用 Map
轻松做到这一点
Map(`/`, countsdata, coldata$Norm)
或者只是复制 'Norm' 并做一个简单的除法
countsdata/coldata$Norm[col(countsdata)]
或者用sweep
sweep(countsdata, 2, coldata$Norm, "/")
我有两个 data.frames,一个有基因型计数,一个有一个数字,我需要从第一个数据集中对我的计数进行标准化。
countsdata=data.frame(genotype1=rep(c(10,20,30,40),each=1),
genotype2=rep(c(100,200,300,400),each=1),
genotype3=rep(c(40,50,60,70),each=1),
genotype4=rep(c(40,50,60,70),each=1)
)
coldata = data.frame(Group =c('genotype1', 'genotype2', 'genotype3', 'genotype4'),
Treatment = rep(c("control","treated"),each = 2),
Norm=rep(c(1,2,5,5)))
我确保我的变量没有因子
factorsCharacter <- function(d) modifyList(d, lapply(d[, sapply(d, is.factor)],
as.character))
coldata=factorsCharacter(coldata)
然后我看到 lapply 循环遍历我的计数,每次一列,并遍历包含归一化值 (Norm) 的 coldata。一切看起来都很好,直到我在同一步骤中组合了两个动作
> lapply(coldata['Group'],function(group_i){group_i})
$Group
[1] "genotype1" "genotype2" "genotype3" "genotype4"
> lapply(coldata['Group'],function(group_i){countsdata[,group_i]})
$Group
genotype1 genotype2 genotype3 genotype4
1 10 100 40 40
2 20 200 50 50
3 30 300 60 60
4 40 400 70 70
> lapply(coldata['Group'],function(group_i){as.integer(coldata[coldata$Group==group_i,'Norm'])})
$Group
[1] 1 2 5 5
> lapply(coldata['Group'],function(group_i){
+ countsdata[,group_i]/as.integer(coldata[coldata$Group==group_i,'Norm'])
+ })
$Group
genotype1 genotype2 genotype3 genotype4
1 10 100 40 40
2 10 100 25 25
3 6 60 12 12
4 8 80 14 14
这里的结果不是我所期望的(将每列除以其归一化数)。进一步检查后,我注意到它是按行规范化的,换句话说,它是跨不同列规范化的,这不应该是这种情况,因为我当时正在循环浏览一列。我可能遗漏了一个基本概念,但浏览其他 SO 帖子没有找到任何我可以使用的东西。我的目标是修复代码以进行正确的计算,但我也想了解为什么上面的代码不起作用。非常感谢。
问题在于使用 [
而不是 [[
。因此,我们没有遍历 'Group' 列中的每个元素,而是有一个包含所有元素的长度为 1 的 list
。因此,使用 coldata[, 'Group']
或 coldata[['Group']]
或 coldata$Group
进行循环。
countsdataNew <- countsdata
countsdataNew[] <- lapply(coldata[['Group']],function(group_i)
countsdata[,group_i]/coldata$Norm[coldata$Group==group_i])
countsdataNew
# genotype1 genotype2 genotype3 genotype4
#1 10 50 8 8
#2 20 100 10 10
#3 30 150 12 12
#4 40 200 14 14
如果 'countsdata' 中的列名和 'countsdata' 中的 'Group' 列的顺序相同,我们可以使用 Map
Map(`/`, countsdata, coldata$Norm)
或者只是复制 'Norm' 并做一个简单的除法
countsdata/coldata$Norm[col(countsdata)]
或者用sweep
sweep(countsdata, 2, coldata$Norm, "/")