假设我有一个包含矩阵列的data.frame。我想把这些变换成单独的列。我在这里看到了这个问题,它给出了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
保留类型,但不保留列名。
使用do.call
和data.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" ...