【问题标题】:Link data.frame and matrix链接 data.frame 和矩阵
【发布时间】:2015-07-01 09:40:35
【问题描述】:

我有一个data.frame 和一个matrix,它们具有相同的行和不同的列数。

matrix 中的所有元素都是整数,但 data.frame 在某些列中包含字符。

我想链接这些文件的行,即如果我删除 matrix 中的一行,data.frame 中的同一行将被自动删除,或者当我对 data.frame 的元素进行排序时列,矩阵中的元素进行相应的排序。

补充说明:我想将matrix 保留为整数矩阵,所以我不能使用cbind

【问题讨论】:

  • cbind他们在一起。
  • cbind的问题是组合矩阵变成了字符矩阵。我想将矩阵保留为integre

标签: r matrix dataframe


【解决方案1】:

对此有(至少)两种解决方案。简单的选择是创建一个新的data.frame,其中包括两行:

样本数据

set.seed(123)
df <- data.frame(ID = 1:26, Group = sample(c("A", "B"), 26, TRUE))
mat <- matrix(rnorm(78), ncol = 3, dimnames = list(1:26, paste0("Val", 1:3)))

新建data.frame,存储矩阵列名供以后参考:

new_df <- cbind(df, mat)
mat_cols <- colnames(mat)

做一些子集:

new_df <- new_df[seq(1, 25, 2), ]

在需要时提取矩阵:

as.matrix(new_df[, mat_cols])

另一个选项是使用 S3 或 S4 类。例如,Bioconductor 包Biobase 有一个ExpressionSet 类,它可以保存matrix 和表型数据,并且子集可以对两者进行子集化(尽管矩阵的行和列是相反的)。

如果您想更简单地做到这一点(ExpressionsSets 可能相对复杂,难以理解),这里有一个 S3 实现:

as.JoinedUp <- function(data_frame, matrix) {
  stopifnot(is.data.frame(data_frame), is.matrix(matrix), nrow(data_frame) == nrow(matrix))
  x <- list(data_frame = data_frame, matrix = matrix)
  class(x) <- "JoinedUp"
  x
}
`[.JoinedUp` <- function(x, i = NULL, j = NULL) {
  if (is.null(i)) {
    i <- 1:nrow(x$data_frame)
  }
  if (is.null(j)) {
    j <- union(colnames(x$data_frame), colnames(x$matrix))
  }
  stopifnot(is.character(j))
  x$data_frame <- x$data_frame[i, intersect(j, colnames(x$data_frame)), drop = FALSE]
  x$matrix <- x$matrix[i, intersect(j, colnames(x$matrix)), drop = FALSE]
  x
}
`[<-.JoinedUp` <- function(x, i = NULL, j = NULL, value) {
  if (is.null(j)) {
    j <- union(colnames(x$data_frame), colnames(x$matrix))
  }
  if (is.null(i)) {
    i <- 1:nrow(x$data_frame)
  }
  stopifnot(is.character(j))
  if (!is.matrix(value) & !is.data.frame(value)) {
    value <- as.data.frame(t(value), stringsAsFactors = FALSE)
  }
  stopifnot(ncol(value) == length(j))
  if (any(j %in% colnames(x$data_frame))) {
    df_cols <- intersect(j, colnames(x$data_frame))
    x$data_frame[i, df_cols] <- value[, match(df_cols, j)]
  }
  if (any(j %in% colnames(x$matrix))) {
    mat_cols <- intersect(j, colnames(x$matrix))
    x$matrix[i, mat_cols] <- data.matrix(value[, match(mat_cols, j)])
  }
  x
}

例子:

new_obj <- as.JoinedUp(df, mat)
new_obj[1:3, ]
new_obj[, c("ID", "Val1")]
new_obj[10:15, ]$matrix
new_obj <- new_obj[order(new_obj$matrix[, "Val1"]), ]
new_obj[1:5, c("ID", "Val1")] <- data.frame(ID = 20:24, Val1 = 0)

这只是你需要的一个骨架;您可能还想为dimnrowncol 等定义方法。

【讨论】:

  • 给我留下了深刻的印象,虽然我知道 S3 类,但我不知道我们可以重载 [ 运算符。
【解决方案2】:

试试这个例子:

#dummy data
set.seed(123)
df1 <- data.frame(ID=1:3, x=letters[1:3])
m1 <- matrix(c(1:3,runif(6)), ncol=3)

#cbind data.frame and matrix, results in a data.frame object
res <- cbind(df1, m1)
res
#   ID x 1         2         3
# 1  1 a 1 0.2875775 0.8830174
# 2  2 b 2 0.7883051 0.9404673
# 3  3 c 3 0.4089769 0.0455565

#subset 2nd row
res[ 2,]
#   ID x 1         2         3
# 2  2 b 2 0.7883051 0.9404673

#order by 4th column
res[ order(res[ ,4 ]), ]
  # ID x 1         2         3
# 1  1 a 1 0.2875775 0.8830174
# 3  3 c 3 0.4089769 0.0455565
# 2  2 b 2 0.7883051 0.9404673

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多