如何将数据框转换为矩阵
How to convert a dataframe to a matrix
我想将命名向量传输到矩阵并填充缺失值(用 0 填充)。
例如,我有这样一个数据框:
col1 col2 col3
Cancer1 Gene1 2.1
Cancer1 Gene2 2.51
Cancer1 Gene3 3.0
Cancer2 Gene1 0.9
其中有两列名称:col1
和 col2
。然后我想把它变成一个矩阵,比如:
Cancer1 Cancer2
Gene1 2.1 0.9
Gene2 2.51 0
Gene3 3.0 0
如果向量中有缺失值,用0填充。
如何在 R 中高效地执行此操作?
您可以进行嵌套应用,遍历每个基因和癌症类型。如果有因子,则使用水平;如果有字符向量,则使用 unique()。
my.df <- data.frame(col1=c("cancer1", "cancer1", "cancer2", "cancer2"),
col2=c("gene1", "gene2", "gene3", "gene1"),
col3=c(2.1, 2.5, 3.0, 2.2))
my.mat <- sapply(levels(my.df$col1), (function(cancer){
sapply(levels(my.df$col2), (function(gene){
tmp <- my.df[my.df$col1 == cancer & my.df$col2 == gene, "col3"]
if (length(tmp) > 0) {
as.numeric(tmp[1])
} else {
NA
}
}))
}))
my.mat
您可以使用 tidyr
包:
tidyr::spread(mydata, col1, col3, fill = 0)
# col2 Cancer1 Cancer2
# 1 Gene1 2.10 0.9
# 2 Gene2 2.51 0.0
# 3 Gene3 3.00 0.0
数据:
mydata <- structure(list(col1 = structure(c(1L, 1L, 1L, 2L), .Label = c("Cancer1",
"Cancer2"), class = "factor"), col2 = structure(c(1L, 2L, 3L,
1L), .Label = c("Gene1", "Gene2", "Gene3"), class = "factor"),
col3 = c(2.1, 2.51, 3, 0.9)), .Names = c("col1", "col2",
"col3"), class = "data.frame", row.names = c(NA, -4L))
xtabs
或 tapply
都应该这样做。
tapply(my.df$col3, rev(my.df[-3]), c)
col1
col2 cancer1 cancer2
gene1 2.1 2.2
gene2 2.5 NA
gene3 NA 3.0
tapply
的优点是,如果任何一个组合有多个实例,您可以 return 将 mean
之类的函数结果应用于该组。
xtabs(col3 ~ col2 +col1, my.df) #same matrix result
请注意,使用像 spread
这样的 tidyverse
方法可能会为您提供 "special" class 的数据对象(不是矩阵),如果您不期望它们可能具有烦人的特性,或者如果您期望它们可能看起来很棒。
我想将命名向量传输到矩阵并填充缺失值(用 0 填充)。
例如,我有这样一个数据框:
col1 col2 col3
Cancer1 Gene1 2.1
Cancer1 Gene2 2.51
Cancer1 Gene3 3.0
Cancer2 Gene1 0.9
其中有两列名称:col1
和 col2
。然后我想把它变成一个矩阵,比如:
Cancer1 Cancer2
Gene1 2.1 0.9
Gene2 2.51 0
Gene3 3.0 0
如果向量中有缺失值,用0填充。
如何在 R 中高效地执行此操作?
您可以进行嵌套应用,遍历每个基因和癌症类型。如果有因子,则使用水平;如果有字符向量,则使用 unique()。
my.df <- data.frame(col1=c("cancer1", "cancer1", "cancer2", "cancer2"),
col2=c("gene1", "gene2", "gene3", "gene1"),
col3=c(2.1, 2.5, 3.0, 2.2))
my.mat <- sapply(levels(my.df$col1), (function(cancer){
sapply(levels(my.df$col2), (function(gene){
tmp <- my.df[my.df$col1 == cancer & my.df$col2 == gene, "col3"]
if (length(tmp) > 0) {
as.numeric(tmp[1])
} else {
NA
}
}))
}))
my.mat
您可以使用 tidyr
包:
tidyr::spread(mydata, col1, col3, fill = 0)
# col2 Cancer1 Cancer2
# 1 Gene1 2.10 0.9
# 2 Gene2 2.51 0.0
# 3 Gene3 3.00 0.0
数据:
mydata <- structure(list(col1 = structure(c(1L, 1L, 1L, 2L), .Label = c("Cancer1",
"Cancer2"), class = "factor"), col2 = structure(c(1L, 2L, 3L,
1L), .Label = c("Gene1", "Gene2", "Gene3"), class = "factor"),
col3 = c(2.1, 2.51, 3, 0.9)), .Names = c("col1", "col2",
"col3"), class = "data.frame", row.names = c(NA, -4L))
xtabs
或 tapply
都应该这样做。
tapply(my.df$col3, rev(my.df[-3]), c)
col1
col2 cancer1 cancer2
gene1 2.1 2.2
gene2 2.5 NA
gene3 NA 3.0
tapply
的优点是,如果任何一个组合有多个实例,您可以 return 将 mean
之类的函数结果应用于该组。
xtabs(col3 ~ col2 +col1, my.df) #same matrix result
请注意,使用像 spread
这样的 tidyverse
方法可能会为您提供 "special" class 的数据对象(不是矩阵),如果您不期望它们可能具有烦人的特性,或者如果您期望它们可能看起来很棒。