목록을 데이터 프레임으로 변환
중첩 된 데이터 목록이 있습니다. 길이는 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 댓글에서 지적) '는 벡터 대신이야.
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 답변과 동일한 결과를 얻습니다.
data.frame(t(sapply(mylistlist,c)))
sapply
그것을 행렬로 변환합니다. data.frame
행렬을 데이터 프레임으로 변환합니다.
목록이라고 가정 L
하고
data.frame(Reduce(rbind, L))
패키지 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)
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>
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 ()를 사용하여 한 줄 로이 작업을 수행 할 수 있습니다.
목록의 구조에 따라 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
이 방법은 tidyverse
패키지 ( purrr )를 사용합니다.
목록 :
x <- as.list(mtcars)
데이터 프레임으로 변환 ( tibble
보다 구체적으로) :
library(purrr)
map_df(x, ~.x)
이 질문에 대한 답변의 타이밍과 함께 더 많은 답변 : 목록을 데이터 프레임으로 캐스팅하는 가장 효율적인 방법은 무엇입니까?
열에 대한 벡터가 아닌 목록이있는 데이터 프레임을 생성하지 않는 가장 빠른 방법은 다음과 같습니다 (마틴 모건의 대답에서).
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]])))
@Marek의 대답으로 확장 : 문자열이 요인으로 바뀌지 않고 효율성을 고려하지 않으려는 경우 시도하십시오.
do.call(rbind, lapply(your_list, data.frame, stringsAsFactors=FALSE))
중첩 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
때로는 데이터가 같은 길이의 벡터 목록 목록 일 수 있습니다.
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
이것이 마침내 나를 위해 일한 것입니다.
do.call("rbind", lapply(S1, as.data.frame))
l <- replicate(10,list(sample(letters, 20)))
a <-lapply(l[1:10],data.frame)
do.call("cbind", a)
솔루션 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)
참고 URL : https://stackoverflow.com/questions/4227223/convert-a-list-to-a-data-frame
'development' 카테고리의 다른 글
쓰기 컨텍스트에서 메서드 반환 값을 사용할 수 없습니다 (0) | 2020.02.15 |
---|---|
저장 프로 시저 / 함수 목록 Mysql Command Line (0) | 2020.02.15 |
문자열에서 텍스트를 제거하는 방법? (0) | 2020.02.15 |
입력“텍스트”태그 자동 확대 비활성화-iPhone의 Safari (0) | 2020.02.15 |
foreach 루프에서 첫 번째와 마지막 반복을 결정하는 방법은 무엇입니까? (0) | 2020.02.15 |