data.목록에 대한 행 프레임
저는 data.frame을 가지고 있는데, 행별로 목록으로 변환하고 싶습니다. 즉, 각 행은 고유한 목록 요소에 해당합니다.즉, data.frame에 행이 있는 목록을 원합니다.
지금까지 저는 이 문제를 다음과 같은 방식으로 다루었는데, 이 문제에 더 잘 접근할 수 있는 방법이 없을까 생각했습니다.
xy.df <- data.frame(x = runif(10), y = runif(10))
# pre-allocate a list and fill it with a loop
xy.list <- vector("list", nrow(xy.df))
for (i in 1:nrow(xy.df)) {
xy.list[[i]] <- xy.df[i,]
}
다음과 같이:
xy.list <- split(xy.df, seq(nrow(xy.df)))
그리고 만약 당신이 의 이름을 원한다면.xy.df
출력 목록의 이름이 되기 위해 다음을 수행할 수 있습니다.
xy.list <- setNames(split(xy.df, seq(nrow(xy.df))), rownames(xy.df))
유레카!
xy.list <- as.list(as.data.frame(t(xy.df)))
보다 현대적인 솔루션에서는purrr::transpose
:
library(purrr)
iris[1:2,] %>% purrr::transpose()
#> [[1]]
#> [[1]]$Sepal.Length
#> [1] 5.1
#>
#> [[1]]$Sepal.Width
#> [1] 3.5
#>
#> [[1]]$Petal.Length
#> [1] 1.4
#>
#> [[1]]$Petal.Width
#> [1] 0.2
#>
#> [[1]]$Species
#> [1] 1
#>
#>
#> [[2]]
#> [[2]]$Sepal.Length
#> [1] 4.9
#>
#> [[2]]$Sepal.Width
#> [1] 3
#>
#> [[2]]$Petal.Length
#> [1] 1.4
#>
#> [[2]]$Petal.Width
#> [1] 0.2
#>
#> [[2]]$Species
#> [1] 1
만약 당신이 (나처럼) data.frame을 완전히 남용하고 $ 기능을 유지하고 싶다면, 한 가지 방법은 당신에게 data.frame을 목록에 수집된 한 줄의 data.frame으로 분할하는 것입니다.
> df = data.frame(x=c('a','b','c'), y=3:1)
> df
x y
1 a 3
2 b 2
3 c 1
# 'convert' into a list of data.frames
ldf = lapply(as.list(1:dim(df)[1]), function(x) df[x[1],])
> ldf
[[1]]
x y
1 a 3
[[2]]
x y
2 b 2
[[3]]
x y
3 c 1
# and the 'coolest'
> ldf[[2]]$y
[1] 2
지적 자위일 뿐만 아니라 data.frame을 라인 목록으로 '변환'할 수 있으며, lapply와 함께 추가로 사용할 때 유용한 $인덱스를 유지합니다(lapply로 전달한 함수가 이 $인덱스를 사용한다고 가정합니다.
몇 가지 추가 옵션:
와 함께asplit
asplit(xy.df, 1)
#[[1]]
# x y
#0.1137 0.6936
#[[2]]
# x y
#0.6223 0.5450
#[[3]]
# x y
#0.6093 0.2827
#....
와 함께split
그리고.row
split(xy.df, row(xy.df)[, 1])
#$`1`
# x y
#1 0.1137 0.6936
#$`2`
# x y
#2 0.6223 0.545
#$`3`
# x y
#3 0.6093 0.2827
#....
데이터.
set.seed(1234)
xy.df <- data.frame(x = runif(10), y = runif(10))
저는 오늘 수백만 개의 관측치와 35개의 열이 있는 data.frame(실제로는 data.table)을 위해 이 작업을 하고 있었습니다.제 목표는 각각 하나의 행이 있는 data.frames(data.table) 목록을 반환하는 것이었습니다.즉, 각 행을 별도의 data.frame으로 분할하여 목록에 저장하고자 했습니다.
여기 제가 생각해 낸 두 가지 방법이 있는데, 대략 3배 더 빠릅니다.split(dat, seq_len(nrow(dat)))
해당 데이터 세트의 경우.아래에서는 7500행, 5열 데이터 세트(홍채가 50회 반복됨)에 대한 세 가지 방법을 벤치마킹합니다.
library(data.table)
library(microbenchmark)
microbenchmark(
split={dat1 <- split(dat, seq_len(nrow(dat)))},
setDF={dat2 <- lapply(seq_len(nrow(dat)),
function(i) setDF(lapply(dat, "[", i)))},
attrDT={dat3 <- lapply(seq_len(nrow(dat)),
function(i) {
tmp <- lapply(dat, "[", i)
attr(tmp, "class") <- c("data.table", "data.frame")
setDF(tmp)
})},
datList = {datL <- lapply(seq_len(nrow(dat)),
function(i) lapply(dat, "[", i))},
times=20
)
반환됩니다.
Unit: milliseconds
expr min lq mean median uq max neval
split 861.8126 889.1849 973.5294 943.2288 1041.7206 1250.6150 20
setDF 459.0577 466.3432 511.2656 482.1943 500.6958 750.6635 20
attrDT 399.1999 409.6316 461.6454 422.5436 490.5620 717.6355 20
datList 192.1175 201.9896 241.4726 208.4535 246.4299 411.2097 20
이전 테스트만큼 차이가 크지는 않지만, 직선입니다.setDF
max(set)를 갖는 런 분포의 모든 수준에서 방법이 훨씬 빠릅니다.DF) < min(분할) 및attr
방법은 일반적으로 두 배 이상 빠릅니다.
네 번째 방법은 단순 내포된 극한 챔피언입니다.lapply
중첩된 목록을 반환합니다.이 방법은 목록에서 data.frame을 구성하는 비용을 예시합니다.게다가, 제가 시도한 모든 방법들은data.frame
함수는 대략 그것보다 몇 배 느렸습니다.data.table
기술.
데이터.
dat <- vector("list", 50)
for(i in 1:50) dat[[i]] <- iris
dat <- setDF(rbindlist(dat))
의 최신 버전인 것 같습니다.purrr
(0.2.2) 패키지가 가장 빠른 솔루션입니다.
by_row(x, function(v) list(v)[[1L]], .collate = "list")$.out
가장 흥미로운 솔루션을 비교해 보겠습니다.
data("Batting", package = "Lahman")
x <- Batting[1:10000, 1:10]
library(benchr)
library(purrr)
benchmark(
split = split(x, seq_len(.row_names_info(x, 2L))),
mapply = .mapply(function(...) structure(list(...), class = "data.frame", row.names = 1L), x, NULL),
purrr = by_row(x, function(v) list(v)[[1L]], .collate = "list")$.out
)
결과:
Benchmark summary:
Time units : milliseconds
expr n.eval min lw.qu median mean up.qu max total relative
split 100 983.0 1060.0 1130.0 1130.0 1180.0 1450 113000 34.3
mapply 100 826.0 894.0 963.0 972.0 1030.0 1320 97200 29.3
purrr 100 24.1 28.6 32.9 44.9 40.5 183 4490 1.0
는 또한우같결얻수있을다니습과를은는리▁with▁result▁same다있▁also니▁the▁get로 같은 결과를 얻을 수 있습니다.Rcpp
:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
List df2list(const DataFrame& x) {
std::size_t nrows = x.rows();
std::size_t ncols = x.cols();
CharacterVector nms = x.names();
List res(no_init(nrows));
for (std::size_t i = 0; i < nrows; ++i) {
List tmp(no_init(ncols));
for (std::size_t j = 0; j < ncols; ++j) {
switch(TYPEOF(x[j])) {
case INTSXP: {
if (Rf_isFactor(x[j])) {
IntegerVector t = as<IntegerVector>(x[j]);
RObject t2 = wrap(t[i]);
t2.attr("class") = "factor";
t2.attr("levels") = t.attr("levels");
tmp[j] = t2;
} else {
tmp[j] = as<IntegerVector>(x[j])[i];
}
break;
}
case LGLSXP: {
tmp[j] = as<LogicalVector>(x[j])[i];
break;
}
case CPLXSXP: {
tmp[j] = as<ComplexVector>(x[j])[i];
break;
}
case REALSXP: {
tmp[j] = as<NumericVector>(x[j])[i];
break;
}
case STRSXP: {
tmp[j] = as<std::string>(as<CharacterVector>(x[j])[i]);
break;
}
default: stop("Unsupported type '%s'.", type2name(x));
}
}
tmp.attr("class") = "data.frame";
tmp.attr("row.names") = 1;
tmp.attr("names") = nms;
res[i] = tmp;
}
res.attr("names") = x.attr("row.names");
return res;
}
이제와비보십오시해교오보와 비교해 .purrr
:
benchmark(
purrr = by_row(x, function(v) list(v)[[1L]], .collate = "list")$.out,
rcpp = df2list(x)
)
결과:
Benchmark summary:
Time units : milliseconds
expr n.eval min lw.qu median mean up.qu max total relative
purrr 100 25.2 29.8 37.5 43.4 44.2 159.0 4340 1.1
rcpp 100 19.0 27.9 34.3 35.8 37.2 93.8 3580 1.0
한 후 apply 를 다 방 df 행 로 변 른 환 목 적 것 입 니 는 다 하 용 을 록 다 음 한 렬 법 은 ▁the 니 ▁an 것 ▁apply ▁list 다 입 ▁is ▁applying ▁then ▁to ▁convert ative ▁waylappy
it: 그에대한기능것:ldf <- lapply(as.matrix(myDF), function(x)x)
나에게 가장 좋은 방법은:
예제 데이터:
Var1<-c("X1",X2","X3")
Var2<-c("X1",X2","X3")
Var3<-c("X1",X2","X3")
Data<-cbind(Var1,Var2,Var3)
ID Var1 Var2 Var3
1 X1 X2 X3
2 X4 X5 X6
3 X7 X8 X9
우리는 그것을 부릅니다.BBmisc
library(BBmisc)
data$lists<-convertRowsToList(data[,2:4])
결과는 다음과 같습니다.
ID Var1 Var2 Var3 lists
1 X1 X2 X3 list("X1", "X2", X3")
2 X4 X5 X6 list("X4","X5", "X6")
3 X7 X8 X9 list("X7,"X8,"X9)
@flodel이 쓴 것처럼:그러면 데이터 프레임이 데이터 프레임의 행 수와 동일한 수의 요소를 가진 목록으로 변환됩니다.
NewList <- split(df, f = seq(nrow(df)))
목록의 각 요소에서 NA가 아닌 열만 선택하는 기능을 추가할 수 있습니다.
NewList2 <- lapply(NewList, function(x) x[,!is.na(x)])
다을사용다대안른는을 사용하는 다른 .library(purrr)
data더 것
flatten(by_row(xy.df, ..f = function(x) flatten_chr(x), .labels = FALSE))
그by_row
의 purrrlyr
패키지가 당신을 위해 이것을 할 것입니다.
이 예는 다음을 보여줍니다.
myfn <- function(row) {
#row is a tibble with one row, and the same number of columns as the original df
l <- as.list(row)
return(l)
}
list_of_lists <- purrrlyr::by_row(df, myfn, .labels=FALSE)$.out
기적으 값된은에서 된 값입니다.myfn
라고 불리는 df의 새 목록 열에 들어갑니다..out
.$.out
위의 문 끝에서 이 열을 즉시 선택하여 목록 목록을 반환합니다.
언급URL : https://stackoverflow.com/questions/3492379/data-frame-rows-to-a-list
'programing' 카테고리의 다른 글
WordPress 콜백 함수에서 게시 메타 가져오기 (0) | 2023.07.10 |
---|---|
[표시]를 사용하여 표시하는 방법자동 완성 재료2의 경우 (0) | 2023.07.10 |
도커화된 몽고의 데이터 초기화 (0) | 2023.07.10 |
Oracle 트리거 ORA-04098: 트리거가 잘못되었으며 재검증에 실패했습니다. (0) | 2023.07.10 |
기지개를 켜다커밋할 수 없습니다.어떻게 진행하거나 중단합니까? (0) | 2023.07.10 |