행렬을 목록으로 변환하려는 경우 목록의 각 요소에 하나의 열이 포함됩니다. list()
또는 as.list()
분명히 작동하지 않으며 지금까지 다음과 같은 동작을 사용하여 해킹을 사용합니다 tapply
.
x <- matrix(1:10,ncol=2)
tapply(x,rep(1:ncol(x),each=nrow(x)),function(i)i)
나는 이것에 완전히 만족하지 않습니다. 아무도 내가 간과하는 더 깨끗한 방법을 알고 있습니까?
(행으로 채워진 목록을 만들기 위해 코드를 다음과 같이 변경할 수 있습니다.
tapply(x,rep(1:nrow(x),ncol(x)),function(i)i)
)
답변
고양이를 스키닝하려면 배열을 dim 속성이없는 것처럼 벡터로 취급합니다.
split(x, rep(1:ncol(x), each = nrow(x)))
답변
개빈의 대답은 간단하고 우아합니다. 그러나 열이 많은 경우 훨씬 빠른 솔루션은 다음과 같습니다.
lapply(seq_len(ncol(x)), function(i) x[,i])
아래 예에서 속도 차이는 6 배입니다.
> x <- matrix(1:1e6, 10)
> system.time( as.list(data.frame(x)) )
user system elapsed
1.24 0.00 1.22
> system.time( lapply(seq_len(ncol(x)), function(i) x[,i]) )
user system elapsed
0.2 0.0 0.2
답변
data.frames는 목록으로 저장됩니다. 따라서 강압이 가장 좋습니다.
as.list(as.data.frame(x))
> as.list(as.data.frame(x))
$V1
[1] 1 2 3 4 5
$V2
[1] 6 7 8 9 10
벤치마킹 결과는 흥미 롭습니다. as.data.frame은 data.frame보다 빠릅니다. 왜냐하면 data.frame이 완전히 새로운 객체를 생성해야하기 때문이거나 열 이름을 추적하는 데 비용이 많이 들기 때문입니다 (c (unname ()) 대 c () 비교를 확인하십시오). )? @Tommy가 제공하는 lapply 솔루션은 훨씬 더 빠릅니다. as.data.frame () 결과는 수동으로 강제로 개선 할 수 있습니다.
manual.coerce <- function(x) {
x <- as.data.frame(x)
class(x) <- "list"
x
}
library(microbenchmark)
x <- matrix(1:10,ncol=2)
microbenchmark(
tapply(x,rep(1:ncol(x),each=nrow(x)),function(i)i) ,
as.list(data.frame(x)),
as.list(as.data.frame(x)),
lapply(seq_len(ncol(x)), function(i) x[,i]),
c(unname(as.data.frame(x))),
c(data.frame(x)),
manual.coerce(x),
times=1000
)
expr min lq
1 as.list(as.data.frame(x)) 176221 183064
2 as.list(data.frame(x)) 444827 454237
3 c(data.frame(x)) 434562 443117
4 c(unname(as.data.frame(x))) 257487 266897
5 lapply(seq_len(ncol(x)), function(i) x[, i]) 28231 35929
6 manual.coerce(x) 160823 167667
7 tapply(x, rep(1:ncol(x), each = nrow(x)), function(i) i) 1020536 1036790
median uq max
1 186486 190763 2768193
2 460225 471346 2854592
3 449960 460226 2895653
4 271174 277162 2827218
5 36784 37640 1165105
6 171088 176221 457659
7 1052188 1080417 3939286
is.list(manual.coerce(x))
[1] TRUE
답변
데이터 프레임으로 변환 한 다음 목록으로 변환하는 것이 작동하는 것 같습니다.
> as.list(data.frame(x))
$X1
[1] 1 2 3 4 5
$X2
[1] 6 7 8 9 10
> str(as.list(data.frame(x)))
List of 2
$ X1: int [1:5] 1 2 3 4 5
$ X2: int [1:5] 6 7 8 9 10
답변
사용 plyr
은 다음과 같은 경우에 정말 유용 할 수 있습니다.
library("plyr")
alply(x,2)
$`1`
[1] 1 2 3 4 5
$`2`
[1] 6 7 8 9 10
attr(,"class")
[1] "split" "list"
답변
나는 이것이 R의 혐오감을 안다. 그리고 나는 이것을 뒷받침 할 평판이별로 많지 않지만, 더 효율적인 for 루프를 찾고있다. 다음 함수를 사용하여 행렬 매트를 열 목록으로 변환합니다.
mat2list <- function(mat)
{
list_length <- ncol(mat)
out_list <- vector("list", list_length)
for(i in 1:list_length) out_list[[i]] <- mat[,i]
out_list
}
mdsummer 및 원래 솔루션과 비교 한 빠른 벤치 마크 :
x <- matrix(1:1e7, ncol=1e6)
system.time(mat2list(x))
user system elapsed
2.728 0.023 2.720
system.time(split(x, rep(1:ncol(x), each = nrow(x))))
user system elapsed
4.812 0.194 4.978
system.time(tapply(x,rep(1:ncol(x),each=nrow(x)),function(i)i))
user system elapsed
11.471 0.413 11.817
답변
새로운 기능 asplit()
은 v3.6의 기본 R에 제공 될 것입니다. 그때까지 @mdsumner의 대답과 비슷한 정신으로 우리도 할 수 있습니다.
split(x, slice.index(x, MARGIN))
의 문서에 따라 asplit()
. 그러나 이전에 표시된 것처럼 모든 split()
기반 솔루션은 @ Tommy ‘s보다 훨씬 느립니다 lapply/`[`
. 이것은 또한 asplit()
최소한 현재의 형태로 새로운 .
split_1 <- function(x) asplit(x, 2L)
split_2 <- function(x) split(x, rep(seq_len(ncol(x)), each = nrow(x)))
split_3 <- function(x) split(x, col(x))
split_4 <- function(x) split(x, slice.index(x, 2L))
split_5 <- function(x) lapply(seq_len(ncol(x)), function(i) x[, i])
dat <- matrix(rnorm(n = 1e6), ncol = 100)
#> Unit: milliseconds
#> expr min lq mean median uq max neval
#> split_1(dat) 16.250842 17.271092 20.26428 18.18286 20.185513 55.851237 100
#> split_2(dat) 52.975819 54.600901 60.94911 56.05520 60.249629 105.791117 100
#> split_3(dat) 32.793112 33.665121 40.98491 34.97580 39.409883 74.406772 100
#> split_4(dat) 37.998140 39.669480 46.85295 40.82559 45.342010 80.830705 100
#> split_5(dat) 2.622944 2.841834 3.47998 2.88914 4.422262 8.286883 100
dat <- matrix(rnorm(n = 1e6), ncol = 1e5)
#> Unit: milliseconds
#> expr min lq mean median uq max neval
#> split_1(dat) 204.69803 231.3023 261.6907 246.4927 289.5218 413.5386 100
#> split_2(dat) 229.38132 235.3153 253.3027 242.0433 259.2280 339.0016 100
#> split_3(dat) 208.29162 216.5506 234.2354 221.7152 235.3539 342.5918 100
#> split_4(dat) 214.43064 221.9247 240.7921 231.0895 246.2457 323.3709 100
#> split_5(dat) 89.83764 105.8272 127.1187 114.3563 143.8771 209.0670 100