【问题标题】:How to use a for loop to extract specific cells from a matrix?如何使用 for 循环从矩阵中提取特定单元格?
【发布时间】:2014-01-24 11:24:53
【问题描述】:

搜索了几个不同的主题,但没有找到完全相同的问题。我有一个平方相关矩阵,其中行/列名是基因。如下所示的矩阵切片。

                Xelaev15073085m Xelaev15073088m Xelaev15073090m Xelaev15073095m
Xelaev15000002m       0.1250128      -0.6368677       0.3119062       0.3980826
Xelaev15000006m       0.4127414      -0.8805597       0.6435158       0.9629489
Xelaev15000007m       0.4012530      -0.8854113       0.6425895       0.9614517

我有一个数据框,其中包含我想从这个大矩阵中提取的基因对。

      V1              V2
1 Xelaev15011657m Xelaev15017932m
2 Xelaev15011587m Xelaev15046612m
3 Xelaev15011594m Xelaev15046616m
4 Xelaev15011597m Xelaev15046617m
5 Xelaev15011603m Xelaev15046624m
6 Xelaev15011654m Xelaev15017928m

我正在尝试遍历数据帧并输出 matrix["gene1","gene2"] 对的矩阵单元(例如比较 Xelaev15073085mXelaev15000002m 时的值 0.1250128)。在单个基因的基础上执行此操作很容易,但是我尝试使用 for 循环为该列表中的数千对执行此操作失败了。在下面的示例中,headedlist 是上面数据帧的样本,FullcorSM 是全相关矩阵。

for(i in headedlist$V1){
   data.frame(i, headedlist[i,2], FullcorSM[i,headedlist[i,2]])
}

以上行是我的第一次尝试并返回 null。我的第二次尝试如下所示。

for(i in 1:nrow(stagelist)){
  write.table(data.frame(stagelist$V1, stagelist$V2, FullcorSM["stagelist$V1","stagelist$V2"]),
              file="sampleout",
              sep="\t",quote=F)
}

返回越界错误。要在FullcorSM["stagelist$V1", "stagelist$V2"] 部分中不带引号的第二个示例返回第一列中每一列的第二列的所有值,更接近我想要的,但仍然缺少一些关于 R 如何解释我的矩阵/数据框语法的知识,但我不清楚修复方法是什么。关于如何进行的任何见解?

【问题讨论】:

  • 我怀疑match 和矩阵索引将允许您在几行中执行此操作而无需循环。但是,如果没有reproducible example,很难编写代码来提供帮助。
  • 关于矩阵的绝妙技巧:您实际要做的就是执行FullcorSM[as.matrix(headedlist)],您将立即获得值的向量。 (只要,也就是说,headedlist 中的所有值实际上都以列名和/或行名的形式出现在矩阵中)。
  • 另外请注意,您第一次尝试只返回NULL 的原因是因为您实际上并没有对循环中选择的每个值执行任何操作for 孤立的循环只是函数(就像 R 中的大多数其他东西一样),NULL 是默认返回值。您可以将这些值分配 以保存它们。否则,R 将简单地查看每个值,说“是的,它就在那里!”继续前进。
  • @Joran,感谢您的澄清,将使用 David 的解决方案,但这对我了解未来的循环很有好处。
  • @sessmurda 如果大卫的回答对你有用,你应该点击它旁边的小复选标记,这样未来的读者就会知道他的回答解决了你的问题。

标签: r for-loop matrix dataframe


【解决方案1】:

您尝试创建的功能实际上是内置在 R 中的。您可以使用另一个双列矩阵从矩阵中提取值,其中第一列代表行名,第二列代表列名。例如:

m = as.matrix(read.table(text="                Xelaev15073085m Xelaev15073088m Xelaev15073090m Xelaev15073095m
Xelaev15000002m       0.1250128      -0.6368677       0.3119062       0.3980826
Xelaev15000006m       0.4127414      -0.8805597       0.6435158       0.9629489
Xelaev15000007m       0.4012530      -0.8854113       0.6425895       0.9614517"))

# note that your subscript matrix has to be a matrix too, not a data frame
n = as.matrix(read.table(text="Xelaev15000002m Xelaev15073088m
Xelaev15000006m Xelaev15073090m"))

# then it's quite simple
print(m[n])
# [1] -0.6368677  0.6435158

【讨论】:

  • 不错。出于某种原因,我认为矩阵索引只适用于数字索引,而不是字符,这将使match 需要。猜不到!
  • +1!您可能应该注意到,如果您尝试使用原始矩阵中不存在的值进行子集化(如 OP 示例中所示),则会收到错误 subscript out of bounds
  • +1!也许是一个愚蠢的问题...... m 中哪些是行名,哪些是列名有关系吗? IE。它会在“相同”的相关矩阵上工作,但碰巧被转置了吗?
  • @Henrik:除非矩阵是对称的,否则这很重要
  • 谢谢!不错的小技巧,我将来肯定会使用。 R 充满了很多漂亮的快捷方式
【解决方案2】:

远没有@David Robinson 的非常好的解决方案那么干净。无论如何,在这里,相关矩阵中哪些基因在行中,哪些在列中,以及下标矩阵是否包含不在相关矩阵中的组合都无关紧要。与@David 的解决方案中的矩阵名称相同:

# combinations of row and column names for original and transposed correlation matrix
m_comb <- c(outer(rownames(m), colnames(m), paste),
            outer(rownames(t(m)), colnames(t(m)), paste))

# 'dim names' in subscript matrix
n_comb <- paste(n[, "V1"], n[, "V2"])

# subset
m[n[n_comb %in% m_comb, ]]
# [1] -0.6368677  0.6435158

更新

另一种可能性,稍微复杂一些,但可能是更有用的输出。首先将相关矩阵读取到数据框df,将下标矩阵读取到数据框df2

# add row names as a column in correlation matrix
df$rows <- rownames(df)

# melt the correlation matrix
library(reshape2)
df3 <- melt(df)

# merge subscript data and correlation data
df4 <- merge(x = df2, y = df3, by.x = c("V1", "V2"), by.y = c("rows", "variable"))
df4
#                V1              V2      value
# 1 Xelaev15000002m Xelaev15073088m -0.6368677
# 2 Xelaev15000006m Xelaev15073090m  0.6435158

【讨论】:

    猜你喜欢
    • 2013-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多