data.frame একটি তালিকা সারি


123

আমার কাছে একটি ডেটা ফ্রেম রয়েছে যা আমি সারিগুলির দ্বারা একটি তালিকায় রূপান্তর করতে চাই, অর্থাত প্রতিটি সারি তার নিজস্ব তালিকার উপাদানগুলির সাথে মিল রাখে। অন্য কথায়, আমি একটি তালিকা চাই যা ডাটা.ফ্রেমে সারি থাকে।

এখনও অবধি, আমি নিম্নলিখিত পদ্ধতিতে এই সমস্যাটি মোকাবিলা করেছি, তবে আমি ভাবছিলাম যে এর কাছে যাওয়ার আরও ভাল উপায় আছে কিনা।

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,]
}

উত্তর:


163

এটার মত:

xy.list <- split(xy.df, seq(nrow(xy.df)))

এবং যদি আপনি চান যে রবনের xy.dfনামগুলি আউটপুট তালিকার নাম হতে পারে তবে আপনি এটি করতে পারেন:

xy.list <- setNames(split(xy.df, seq(nrow(xy.df))), rownames(xy.df))

4
দ্রষ্টব্য, splitপ্রতিটি উপাদান ব্যবহারের data.frame with 1 rows and N columnsপরিবর্তে টাইপ করুনlist of length N
করোল ডানিলুক

আমি কেবল এটি যুক্ত করব যে আপনি যদি ব্যবহার করেন তবে splitসম্ভবত এটি করা উচিত drop=Tঅন্যথায় কারণগুলির জন্য আপনার মূল স্তরটি হ্রাস পাবে না
ডেনিস

51

ইউরেকা!

xy.list <- as.list(as.data.frame(t(xy.df)))

1
কীভাবে প্রয়োগ করবেন তা প্রদর্শন করার জন্য যত্নশীল?
রোমান Luštrik

3
unlist(apply(xy.df, 1, list), recursive = FALSE)। তবে ফ্লোডেলের দ্রবণটি ব্যবহার করা applyবা ব্যবহারের চেয়ে বেশি দক্ষ t
অরুণ

11
এখানে সমস্যা হল tধর্মান্তরিত data.fameএকটি থেকে matrixযাতে আপনার তালিকায় উপাদান পারমাণবিক ভেক্টর তালিকা হিসাবে ওপি অনুরোধ, তাই না। আপনার xy.dfমিশ্র প্রকারগুলি না হওয়া পর্যন্ত এটি সাধারণত সমস্যা হয় না ...
Calimo

2
আপনি যদি মানগুলি লুপ করতে চান তবে আমি প্রস্তাব দিই না apply। এটি আসলে আর এ প্রয়োগ করা লুপের জন্য একটি মাত্র lapplyসি এর মধ্যে লুপিং সম্পাদন করে যা উল্লেখযোগ্যভাবে দ্রুত faster এই তালিকাগুলির সারিগুলির ফর্ম্যাটটি যদি আপনি অনেকগুলি লুপিং করেন তবে প্রকৃত পক্ষে ভাল।
লিজ স্যান্ডার

1
ভবিষ্যত থেকে অন্য মন্তব্য যুক্ত করা, একটি applyসংস্করণ হ'ল.mapply(data.frame, xy.df, NULL)
অ্যালেক্সিস_লাজ

15

আপনি যদি ডেটা ফ্রেমটিকে পুরোপুরি অপব্যবহার করতে চান (যেমনটি আমি করি) এবং $ কার্যকারিতা রাখতে চান, তবে একটি উপায় হ'ল ডেটা.ফ্রেমকে এক-লাইন ডেটাতে বিভক্ত করুন ra ফ্রেমে একটি তালিকায় জড়িত:

> 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

এটি কেবল বৌদ্ধিক হস্তমৈথুনই নয়, ডাটা f ফ্রেমটিকে তার রেখার তালিকায় 'রূপান্তর' করতে দেয় $ সূচকটি যা ল্যাপলির সাহায্যে আরও ব্যবহারের জন্য কার্যকর হতে পারে (আপনি যে ফাংশনটি অবিচ্ছিন্নভাবে পাস করেন তা ধরে নিচ্ছেন এই $ সূচকটি ব্যবহার করে)


কীভাবে আমরা তাদের আবার একত্রিত করব? এর একটি তালিকা data.frameএকক মধ্যে পরিণত data.frame?
অ্যারন ম্যাকডেইড

4
@ অ্যারোনম্যাকডেইড আপনি do.call এবং rbind ব্যবহার করতে পারেন: df == do.call ("rbind", ldf)
এলোমেলো_আরোস্ট_ফ্যান্যাটিক

@ অ্যারোনমিসডেইড বা ডেটা.ট্যাবল :: rbindlist ()। যদি আপনার আসল ডেটা ফ্রেমটি বড় ছিল, গতি লাভটি উল্লেখযোগ্য হবে।
এম্পিরোমেন্সার

8

আরও আধুনিক সমাধান কেবল ব্যবহার করে 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

8

আমি আজ লক্ষ লক্ষ পর্যবেক্ষণ এবং 35 টি কলাম সহ একটি ডেটা.ফ্রেমের (সত্যই একটি ডেটা টেবিল) জন্য কাজ করছি। আমার লক্ষ্যটি ছিল প্রতিটি একক সারিতে ডেটা.ফ্রেমস (ডেটা টেবিল) এর তালিকা ফিরিয়ে দেওয়া। এটি হ'ল, আমি প্রতিটি সারি পৃথক ডেটা.ফ্রেমে বিভক্ত করতে চেয়েছিলাম এবং এগুলিকে একটি তালিকাতে সঞ্চয় করতে চাই।

আমি এখানে দুটি পদ্ধতি নিয়ে এসেছি split(dat, seq_len(nrow(dat)))যেগুলি ডেটা সেটের চেয়ে প্রায় 3 গুণ বেশি দ্রুত ছিল । নীচে, আমি 7500 সারি, পাঁচটি কলাম ডেটা সেট ( আইরিস 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সর্বোচ্চ (সেটডিএফ) <মিনিট (বিভক্ত) দিয়ে রান বিতরণের সমস্ত স্তরে সরল পদ্ধতি উল্লেখযোগ্যভাবে দ্রুত এবং attrপদ্ধতিটি সাধারণত দ্বিগুণের চেয়ে দ্রুততর হয়।

চতুর্থ পদ্ধতিটি চূড়ান্ত চ্যাম্পিয়ন, যা সাধারণ নেস্টেড lapply, নেস্টেড তালিকা ফিরিয়ে দেয়। এই পদ্ধতিটি তালিকা থেকে ডেটা.ফ্রেম নির্মাণের ব্যয়ের উদাহরণ দেয়। তদুপরি, আমি data.frameফাংশনটি দিয়ে চেষ্টা করেছি সমস্ত পদ্ধতিগুলি data.tableকৌশলগুলির চেয়ে ধীরে ধীরে মাত্রার ক্রম ছিল ।

উপাত্ত

dat <- vector("list", 50)
for(i in 1:50) dat[[i]] <- iris
dat <- setDF(rbindlist(dat))

6

মনে হচ্ছে purrr(0.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
)

Rsults:

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

এছাড়াও আমরা একই ফলাফল পেতে পারি 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

150 সারিগুলির একটি ছোট্ট ডেটা সেট বেঞ্চমার্কিং এর অর্থ খুব বেশি বোঝায় না যে কেউ মাইক্রোসেকেন্ডে কোনও পার্থক্য লক্ষ্য করবে না এবং এটি স্কেলও করে না
ডেভিড আরেনবার্গ ২

4
by_row()এখন স্থানান্তরিত হয়েছেlibrary(purrrlyr)
মিঃহপকো

এবং purrrlyr মধ্যে থাকা ছাড়াও, এটি হ্রাস করা প্রায়। একই ফলাফল অর্জনের জন্য এখন আরও পরিষ্কার পদ্ধতি :: ন্যাড, ডিপ্লাইার :: মিউটেট পুরির :: ম্যাপ সংযুক্ত করার অন্যান্য পদ্ধতি রয়েছে
মাইক স্ট্যানলি

3

আরও কয়েকটি বিকল্প:

সঙ্গে 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))

2

আমার জন্য সবচেয়ে ভাল উপায় ছিল:

উদাহরণ ডেটা:

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) 

1

বিকল্প উপায় হ'ল ডিএফকে ম্যাট্রিক্সে রূপান্তর করা তারপরে তালিকাটি প্রয়োগ lappyকরে এটির উপরে ফাংশন প্রয়োগ করুন :ldf <- lapply(as.matrix(myDF), function(x)x)


1

ব্যবহারের আরেকটি বিকল্প library(purrr)(এটি বৃহত ডেটা.ফ্রেমে কিছুটা দ্রুত বলে মনে হচ্ছে)

flatten(by_row(xy.df, ..f = function(x) flatten_chr(x), .labels = FALSE))

3
`বাই_রো () now এখন` লাইব্রেরীতে চলে গেছে (পুরুলার)
Mr

1

যেমন @ ফ্লোডেল লিখেছেন: এটি আপনার ডেটাফ্রেমকে একটি তালিকায় রূপান্তর করে যা ডাটাফ্রেমে সারি সংখ্যার মতো উপাদানগুলির সমান সংখ্যক উপাদান রয়েছে:

NewList <- split(df, f = seq(nrow(df)))

তালিকার প্রতিটি উপাদানগুলিতে NA নয় এমন কলামগুলি নির্বাচন করতে আপনি অতিরিক্ত একটি ফাংশন যুক্ত করতে পারেন :

NewList2 <- lapply(NewList, function(x) x[,!is.na(x)])

0

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নতুন তালিকার কলামে স্থাপন করা হয় .out$.outউপরের বিবৃতি শেষে অবিলম্বে এই কলামটি নির্বাচন, তালিকা একটি তালিকা ফিরিয়ে আনে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.