【问题标题】:split matrix-column without intermediate conversion to matrix拆分矩阵列,无需中间转换为矩阵
【发布时间】:2021-11-20 20:30:49
【问题描述】:

假设我有一个包含矩阵列的 data.frame。我想将这些转换为单独的列。我见过this question here,这表明as.data.frame(as.matrix(...)) 是一个很好的解决方案。但是,如果 data.frame 的列/矩阵列是数字和字符的混合,则转换为矩阵会将 所有 列转换为字符。

我可以通过蛮力、遍历列等来做到这一点,但必须有一种更优雅的方式来做到这一点。我玩过类似do.call(cbind, sapply(..., data.frame)) 这样的东西,它实际上保留了数字/字符,但破坏了不太理想的列名(而 matrix-data.frame 转换使列名看起来不错)。

例如,

> data(mtcars)
> mtcars$car <- row.names(mtcars)
> m <- model.frame(cbind(gear, am) ~ car, data = mtcars)
> head(m)
                  cbind(gear, am).gear cbind(gear, am).am               car
Mazda RX4                            4                  1         Mazda RX4
Mazda RX4 Wag                        4                  1     Mazda RX4 Wag
Datsun 710                           4                  1        Datsun 710
Hornet 4 Drive                       3                  0    Hornet 4 Drive
Hornet Sportabout                    3                  0 Hornet Sportabout
Valiant                              3                  0           Valiant
> str(m, give.attr = FALSE)
'data.frame':   32 obs. of  2 variables:
 $ cbind(gear, am): num [1:32, 1:2] 4 4 4 3 3 3 3 4 4 4 ...
 $ car            : chr  "Mazda RX4" "Mazda RX4 Wag" "Datsun 710" "Hornet 4 Drive" ...
> dim(m)
[1] 32  2
> m2 <- as.data.frame(as.matrix(m))
> head(m2)
                  cbind(gear, am).gear cbind(gear, am).am               car
Mazda RX4                            4                  1         Mazda RX4
Mazda RX4 Wag                        4                  1     Mazda RX4 Wag
Datsun 710                           4                  1        Datsun 710
Hornet 4 Drive                       3                  0    Hornet 4 Drive
Hornet Sportabout                    3                  0 Hornet Sportabout
Valiant                              3                  0           Valiant
> str(m2, give.attr = FALSE)
'data.frame':   32 obs. of  3 variables:
 $ cbind(gear, am).gear: chr  "4" "4" "4" "3" ...
 $ cbind(gear, am).am  : chr  "1" "1" "1" "0" ...
 $ car                 : chr  "Mazda RX4" "Mazda RX4 Wag" "Datsun 710" "Hornet 4 Drive" ...
> dim(m2)
[1] 32  3
> m3 <- do.call(cbind, sapply(m, data.frame))
> head(m3)
  cbind(gear, am).gear cbind(gear, am).am            X..i..
1                    4                  1         Mazda RX4
2                    4                  1     Mazda RX4 Wag
3                    4                  1        Datsun 710
4                    3                  0    Hornet 4 Drive
5                    3                  0 Hornet Sportabout
6                    3                  0           Valiant
> str(m3, give.attr = FALSE)
'data.frame':   32 obs. of  3 variables:
 $ cbind(gear, am).gear: num  4 4 4 3 3 3 3 4 4 4 ...
 $ cbind(gear, am).am  : num  1 1 1 0 0 0 0 0 0 0 ...
 $ X..i..              : chr  "Mazda RX4" "Mazda RX4 Wag" "Datsun 710" "Hornet 4 Drive" ...
> dim(m3)
[1] 32  3

在此示例中,m2 保留列名但丢失类型,而 m3 保留类型但丢失列名。

【问题讨论】:

    标签: r matrix


    【解决方案1】:

    do.calldata.frame 一起使用

    m4 <- do.call(data.frame, c(m, check.names = FALSE)) 
    

    -输出结构

    > str(m4)
    'data.frame':   32 obs. of  3 variables:
     $ cbind(gear, am).gear: num  4 4 4 3 3 3 3 4 4 4 ...
     $ cbind(gear, am).am  : num  1 1 1 0 0 0 0 0 0 0 ...
     $ car                 : chr  "Mazda RX4" "Mazda RX4 Wag" "Datsun 710" "Hornet 4 Drive" ...
    

    在派生“m3”的第三种情况下,OP 使用sapply 循环遍历data.frame 'm' 的列,然后转换为data.frame。但是,它对展平没有任何作用,即来自matrix 的列在list 中被转换为data.frame,并且列名中的X.. 是从内部名称派生的,因为'car',原始' 中的列m' 被强制转换为没有默认列名的 data.frame

    > str(sapply(m, data.frame))
    List of 2
     $ cbind(gear, am):'data.frame':    32 obs. of  2 variables:
      ..$ gear: num [1:32] 4 4 4 3 3 3 3 4 4 4 ...
      ..$ am  : num [1:32] 1 1 1 0 0 0 0 0 0 0 ...
     $ car            :'data.frame':    32 obs. of  1 variable:
      ..$ X..i..: chr [1:32] "Mazda RX4" "Mazda RX4 Wag" "Datsun 710" "Hornet 4 Drive" ...
    

    【讨论】:

    • 对于m3,我试图将data.frame 转换为可以传递给do.call 的列/矩阵列表。可能还有更好的方法来做到这一点。
    • @Josh 你可以使用asplit(do.call(data.frame, m), 2)unclass(do.call(data.frame, m))
    猜你喜欢
    • 2015-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-03
    • 2021-08-17
    • 2013-04-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多