중첩 된 데이터 목록이 있습니다. 길이는 132이고 각 항목은 길이가 20 인 목록입니다. 이 구조를 132 행과 20 열의 데이터가있는 데이터 프레임으로 변환 하는 빠른 방법이 있습니까?
다음은 사용할 샘플 데이터입니다.
l <- replicate(
132,
list(sample(letters, 20)),
simplify = FALSE
)
중첩 된 데이터 목록이 있습니다. 길이는 132이고 각 항목은 길이가 20 인 목록입니다. 이 구조를 132 행과 20 열의 데이터가있는 데이터 프레임으로 변환 하는 빠른 방법이 있습니까?
다음은 사용할 샘플 데이터입니다.
l <- replicate(
132,
list(sample(letters, 20)),
simplify = FALSE
)
답변:
목록의 목록을 다음과 같이 가정합니다 l
.
df <- data.frame(matrix(unlist(l), nrow=length(l), byrow=T))
위의 모든 문자 열을 인수로 변환하여 data.frame () 호출에 매개 변수를 추가 할 수 있습니다.
df <- data.frame(matrix(unlist(l), nrow=132, byrow=T),stringsAsFactors=FALSE)
와 rbind
do.call(rbind.data.frame, your_list)
편집 : 이전 버전 반환 data.frame
의 list
(@IanSudbery 댓글에서 지적) '는 벡터 대신이야.
rbind(your_list)
1x32 목록 행렬을 반환합니까?
do.call
요소를 your_list
전달합니다 rbind
. 와 동일 rbind(your_list[[1]], your_list[[2]], your_list[[3]], ....., your_list[[length of your_list]])
합니다.
your_list
동일한 크기의 벡터 를 포함 해야합니다 . NULL
길이가 0이므로 실패해야합니다.
plyr
패키지 를 사용할 수 있습니다 . 예를 들어 양식의 중첩 목록
l <- list(a = list(var.1 = 1, var.2 = 2, var.3 = 3)
, b = list(var.1 = 4, var.2 = 5, var.3 = 6)
, c = list(var.1 = 7, var.2 = 8, var.3 = 9)
, d = list(var.1 = 10, var.2 = 11, var.3 = 12)
)
이제 길이가 4이고 각 목록 l
의 길이가 3 인 다른 목록이 있습니다. 이제 실행할 수 있습니다
library (plyr)
df <- ldply (l, data.frame)
@Marek 및 @nico 답변과 동일한 결과를 얻습니다.
matrix
접근 방식 으로 문자로 변환됩니다 .
data.frame(t(sapply(mylistlist,c)))
sapply
그것을 행렬로 변환합니다.
data.frame
행렬을 데이터 프레임으로 변환합니다.
c
목록 데이터의 한 인스턴스 인 여기에서 어떤 역할을 하시겠습니까? 연결 함수를 기다립니다. c? @mnel의 사용법과 혼동되기 c. 또한 @dchandler와 동의하여 열 이름을 올바르게 사용하는 것이 유스 케이스에서 중요한 요구 사항이었습니다. 훌륭한 솔루션.
?c
:Combine Values into a Vector or List
목록이라고 가정 L
하고
data.frame(Reduce(rbind, L))
data.frame(Reduce(rbind, list(c('col1','col2'))))
있는 데이터 프레임을 생성합니다 (1 개의 행 2 개의 열
패키지 data.table
에는의 rbindlist
초고속 구현 기능 이 do.call(rbind, list(...))
있습니다.
이 목록을 취할 수 lists
, data.frames
또는 data.tables
입력으로.
library(data.table)
ll <- list(a = list(var.1 = 1, var.2 = 2, var.3 = 3)
, b = list(var.1 = 4, var.2 = 5, var.3 = 6)
, c = list(var.1 = 7, var.2 = 8, var.3 = 9)
, d = list(var.1 = 10, var.2 = 11, var.3 = 12)
)
DT <- rbindlist(ll)
이에서 data.table
상속을 반환합니다 data.frame
.
당신이 경우 정말 data.frame 사용으로 다시 변환 할as.data.frame(DT)
setDF
이제 참조로 data.frame으로 돌아갈 수 있습니다.
tibble
패키지 기능을 갖는 enframe()
로 해결할 중첩 강요함으로써이 문제 있음 list
중첩에 객체 tibble
( "단정"데이터 프레임) 객체. 다음은 R for Data Science 의 간단한 예입니다 .
x <- list(
a = 1:5,
b = 3:4,
c = 5:6
)
df <- enframe(x)
df
#> # A tibble: 3 × 2
#> name value
#> <chr> <list>
#> 1 a <int [5]>
#> 2 b <int [2]>
#> 3 c <int [2]>
목록에 여러 개의 중첩 l
이 있으므로를 사용하여 unlist(recursive = FALSE)
불필요한 중첩을 제거하여 단일 계층 목록 만 가져온 다음에 전달할 수 enframe()
있습니다. 나는 사용 tidyr::unnest()
하여 두 개의 열 (그룹의 하나가 하나의 수준 "단정"데이터 프레임에 출력 unnest로 name
하고, 그룹과 관찰을위한 하나 value
). 너비가 넓은 열을 원하면 add_column()
값의 순서를 132 번 반복 하여 열을 추가 할 수 있습니다 . 그런 다음 spread()
값만.
library(tidyverse)
l <- replicate(
132,
list(sample(letters, 20)),
simplify = FALSE
)
l_tib <- l %>%
unlist(recursive = FALSE) %>%
enframe() %>%
unnest()
l_tib
#> # A tibble: 2,640 x 2
#> name value
#> <int> <chr>
#> 1 1 d
#> 2 1 z
#> 3 1 l
#> 4 1 b
#> 5 1 i
#> 6 1 j
#> 7 1 g
#> 8 1 w
#> 9 1 r
#> 10 1 p
#> # ... with 2,630 more rows
l_tib_spread <- l_tib %>%
add_column(index = rep(1:20, 132)) %>%
spread(key = index, value = value)
l_tib_spread
#> # A tibble: 132 x 21
#> name `1` `2` `3` `4` `5` `6` `7` `8` `9` `10` `11`
#> * <int> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
#> 1 1 d z l b i j g w r p y
#> 2 2 w s h r i k d u a f j
#> 3 3 r v q s m u j p f a i
#> 4 4 o y x n p i f m h l t
#> 5 5 p w v d k a l r j q n
#> 6 6 i k w o c n m b v e q
#> 7 7 c d m i u o e z v g p
#> 8 8 f s e o p n k x c z h
#> 9 9 d g o h x i c y t f j
#> 10 10 y r f k d o b u i x s
#> # ... with 122 more rows, and 9 more variables: `12` <chr>, `13` <chr>,
#> # `14` <chr>, `15` <chr>, `16` <chr>, `17` <chr>, `18` <chr>,
#> # `19` <chr>, `20` <chr>
목록의 구조에 따라 tidyverse
길이가 다른 목록과 잘 작동 하는 몇 가지 옵션이 있습니다.
l <- list(a = list(var.1 = 1, var.2 = 2, var.3 = 3)
, b = list(var.1 = 4, var.2 = 5)
, c = list(var.1 = 7, var.3 = 9)
, d = list(var.1 = 10, var.2 = 11, var.3 = NA))
df <- dplyr::bind_rows(l)
df <- purrr::map_df(l, dplyr::bind_rows)
df <- purrr::map_df(l, ~.x)
# all create the same data frame:
# A tibble: 4 x 3
var.1 var.2 var.3
<dbl> <dbl> <dbl>
1 1 2 3
2 4 5 NA
3 7 NA 9
4 10 11 NA
벡터와 데이터 프레임을 혼합 할 수도 있습니다.
library(dplyr)
bind_rows(
list(a = 1, b = 2),
data_frame(a = 3:4, b = 5:6),
c(a = 7)
)
# A tibble: 4 x 2
a b
<dbl> <dbl>
1 1 2
2 3 5
3 4 6
4 7 NA
X2
문자로 정수로 변환 할 수 없습니다
Reshape2는 위 plyr 예제와 동일한 출력을 생성합니다.
library(reshape2)
l <- list(a = list(var.1 = 1, var.2 = 2, var.3 = 3)
, b = list(var.1 = 4, var.2 = 5, var.3 = 6)
, c = list(var.1 = 7, var.2 = 8, var.3 = 9)
, d = list(var.1 = 10, var.2 = 11, var.3 = 12)
)
l <- melt(l)
dcast(l, L1 ~ L2)
수율 :
L1 var.1 var.2 var.3
1 a 1 2 3
2 b 4 5 6
3 c 7 8 9
4 d 10 11 12
픽셀이 거의 없으면 recast ()를 사용하여 한 줄 로이 작업을 수행 할 수 있습니다.
중첩 JSON에서 얻은 것과 같은 수준이 3 개 이상인 깊게 중첩 된 목록의 일반적인 경우 :
{
"2015": {
"spain": {"population": 43, "GNP": 9},
"sweden": {"population": 7, "GNP": 6}},
"2016": {
"spain": {"population": 45, "GNP": 10},
"sweden": {"population": 9, "GNP": 8}}
}
melt()
먼저 중첩 목록을 긴 형식으로 변환 하는 방법을 고려하십시오 .
myjson <- jsonlite:fromJSON(file("test.json"))
tall <- reshape2::melt(myjson)[, c("L1", "L2", "L3", "value")]
L1 L2 L3 value
1 2015 spain population 43
2 2015 spain GNP 9
3 2015 sweden population 7
4 2015 sweden GNP 6
5 2016 spain population 45
6 2016 spain GNP 10
7 2016 sweden population 9
8 2016 sweden GNP 8
다음에 dcast()
각 변수가 각 단 칼럼 관찰 형태 행을 형성 단정 세트로 다시 폭으로 다음 :
wide <- reshape2::dcast(tall, L1+L2~L3)
# left side of the formula defines the rows/observations and the
# right side defines the variables/measurements
L1 L2 GNP population
1 2015 spain 9 43
2 2015 sweden 6 7
3 2016 spain 10 45
4 2016 sweden 8 9
이 질문에 대한 답변의 타이밍과 함께 더 많은 답변 : 목록을 데이터 프레임으로 캐스팅하는 가장 효율적인 방법은 무엇입니까?
열에 대한 벡터가 아닌 목록이있는 데이터 프레임을 생성하지 않는 가장 빠른 방법은 다음과 같습니다 (마틴 모건의 대답에서).
l <- list(list(col1="a",col2=1),list(col1="b",col2=2))
f = function(x) function(i) unlist(lapply(x, `[[`, i), use.names=FALSE)
as.data.frame(Map(f(l), names(l[[1]])))
때로는 데이터가 같은 길이의 벡터 목록 목록 일 수 있습니다.
lolov = list(list(c(1,2,3),c(4,5,6)), list(c(7,8,9),c(10,11,12),c(13,14,15)) )
(내부 벡터도 목록이 될 수 있지만 이것을 쉽게 읽을 수 있도록 단순화하고 있습니다).
그런 다음 다음과 같이 수정할 수 있습니다. 한 번에 하나의 레벨을 나열 해제 할 수 있습니다.
lov = unlist(lolov, recursive = FALSE )
> lov
[[1]]
[1] 1 2 3
[[2]]
[1] 4 5 6
[[3]]
[1] 7 8 9
[[4]]
[1] 10 11 12
[[5]]
[1] 13 14 15
이제 다른 답변에서 언급 한 좋아하는 방법을 사용하십시오.
library(plyr)
>ldply(lov)
V1 V2 V3
1 1 2 3
2 4 5 6
3 7 8 9
4 10 11 12
5 13 14 15
솔루션 purrr
제품군을 사용하는 병렬 (멀티 코어, 멀티 세션 등) 솔루션의 경우 다음을 사용하십시오.
library (furrr)
plan(multisession) # see below to see which other plan() is the more efficient
myTibble <- future_map_dfc(l, ~.x)
l
목록은 어디에 있습니까 ?
가장 효율적인 벤치마킹 방법은 plan()
다음과 같습니다.
library(tictoc)
plan(sequential) # reference time
# plan(multisession) # benchamark plan() goes here. See ?plan().
tic()
myTibble <- future_map_dfc(l, ~.x)
toc()
다음과 같은 간단한 명령이 나를 위해 일했습니다.
myDf <- as.data.frame(myList)
참조 ( Quora answer )
> myList <- list(a = c(1, 2, 3), b = c(4, 5, 6))
> myList
$a
[1] 1 2 3
$b
[1] 4 5 6
> myDf <- as.data.frame(myList)
a b
1 1 4
2 2 5
3 3 6
> class(myDf)
[1] "data.frame"
그러나 목록을 데이터 프레임으로 변환하는 방법이 확실하지 않으면 실패합니다.
> myList <- list(a = c(1, 2, 3), b = c(4, 5, 6, 7))
> myDf <- as.data.frame(myList)
Error in (function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE, :
arguments imply differing number of rows: 3, 4
참고 : 답변은 질문의 제목에 대한 것이며 질문의 세부 사항을 건너 뛸 수 있습니다
데이터 프레임은 길이가 동일한 벡터 의 목록 이기 때문에 짧은 r (아마도 가장 빠르지는 않은) 방법은 base r을 사용하는 것 입니다. 따라서 입력 목록과 30 x 132 data.frame 간의 변환은 다음과 같습니다.
df <- data.frame(l)
거기에서 132 x 30 행렬로 바꾸고 다시 데이터 프레임으로 변환 할 수 있습니다.
new_df <- data.frame(t(df))
원 라이너로 :
new_df <- data.frame(t(data.frame(l)))
행 이름은보기에 꽤 성가 시겠지만 언제든지 이름을 바꿀 수 있습니다.
rownames(new_df) <- 1:nrow(new_df)
사용은 어떻습니까 map_
과 기능을 함께를 for
루프? 내 해결책은 다음과 같습니다.
list_to_df <- function(list_to_convert) {
tmp_data_frame <- data.frame()
for (i in 1:length(list_to_convert)) {
tmp <- map_dfr(list_to_convert[[i]], data.frame)
tmp_data_frame <- rbind(tmp_data_frame, tmp)
}
print(tmp_data_frame)
}
여기서 map_dfr
각 목록 요소를 data.frame으로 변환 한 다음 rbind
완전히 결합하십시오.
귀하의 경우에는 다음과 같습니다.
converted_list <- list_to_df(l)