r - একাধিক কলাম(গুলি) দ্বারা একটি ডাটাফ্রেম সাজানোর কিভাবে?




sorting dataframe (12)

আমি একাধিক কলাম দ্বারা একটি data.frame বাছাই করতে চান। উদাহরণস্বরূপ, নীচের data.frame দিয়ে আমি কলাম z (ঊর্ধ্বমুখী) দ্বারা কলাম b অনুসারে ক্রম বিন্যাস করতে চাই (আরোহী):

dd <- data.frame(b = factor(c("Hi", "Med", "Hi", "Low"), 
      levels = c("Low", "Med", "Hi"), ordered = TRUE),
      x = c("A", "D", "A", "C"), y = c(8, 3, 9, 9),
      z = c(1, 1, 1, 2))
dd
    b x y z
1  Hi A 8 1
2 Med D 3 1
3  Hi A 9 1
4 Low C 9 2

আপনার পছন্দ

  • base থেকে order
  • dplyr থেকে arrange
  • setorder থেকে setorder এবং data.table
  • plyr থেকে arrange
  • taRifx থেকে taRifx
  • orderBy দ্বারা doBy
  • sortData থেকে Deducer

অধিকাংশ সময় আপনি dplyr বা data.table সমাধান ব্যবহার করা উচিত, যদি না নির্ভর-নির্ভরতা গুরুত্বপূর্ণ না হয়, তবে কোন ক্ষেত্রে base::order ব্যবহার করুন।

আমি সম্প্রতি sort.data.frame একটি CRAN প্যাকেজে যোগ করেছি, এটি এখানে আলোচনা হিসাবে শ্রেণীবদ্ধ সামঞ্জস্যপূর্ণ করে তোলে: sort.data.frame এর জন্য জেনেরিক / পদ্ধতি সামঞ্জস্য তৈরি করার সেরা উপায়?

অতএব, data.frame dd দেওয়া, আপনি নিম্নরূপ সাজানোর করতে পারেন:

dd <- data.frame(b = factor(c("Hi", "Med", "Hi", "Low"), 
      levels = c("Low", "Med", "Hi"), ordered = TRUE),
      x = c("A", "D", "A", "C"), y = c(8, 3, 9, 9),
      z = c(1, 1, 1, 2))
library(taRifx)
sort(dd, f= ~ -z + b )

আপনি যদি এই ফাংশনের মূল লেখকগুলির মধ্যে একজন হন তবে আমার সাথে যোগাযোগ করুন। পাবলিক ডোমিনিনিয়ার মত আলোচনা এখানে রয়েছে: http://chat..com/transcript/message/1094290#1094290

আপনি plyr থেকে plyr arrange() ফাংশনটিও ব্যবহার করতে পারেন যেমন plyr উপরের থ্রেডে উল্লেখ করেছেন:

library(plyr)
arrange(dd,desc(z),b)

Benchmarks: অনেক দ্বন্দ্ব ছিল যেহেতু একটি নতুন আর অধিবেশন প্রতিটি প্যাকেজ লোড করা মনে রাখবেন। বিশেষভাবে লোড করার কারণে doBy প্যাকেজটি ফিরে যাওয়ার কারনে "নিম্নোক্ত বস্তু (গুলি) 'x (অবস্থান 17)' থেকে sort.data.frame : বি, এক্স, ই, জে", এবং ডেডুকার প্যাকেজ লোড করা হচ্ছে কেভিন থেকে sort.data.frame overwrites রাইট বা taRifx প্যাকেজ।

#Load each time
dd <- data.frame(b = factor(c("Hi", "Med", "Hi", "Low"), 
      levels = c("Low", "Med", "Hi"), ordered = TRUE),
      x = c("A", "D", "A", "C"), y = c(8, 3, 9, 9),
      z = c(1, 1, 1, 2))
library(microbenchmark)

# Reload R between benchmarks
microbenchmark(dd[with(dd, order(-z, b)), ] ,
    dd[order(-dd$z, dd$b),],
    times=1000
)

মধ্যযুগীয় সময়:

dd[with(dd, order(-z, b)), ] 778

dd[order(-dd$z, dd$b),] 788

library(taRifx)
microbenchmark(sort(dd, f= ~-z+b ),times=1000)

মধ্যযুগীয় সময়: 1,567

library(plyr)
microbenchmark(arrange(dd,desc(z),b),times=1000)

মধ্যযুগীয় সময়: 86২

library(doBy)
microbenchmark(orderBy(~-z+b, data=dd),times=1000)

মধ্যযুগীয় সময়: 1,694

উল্লেখ্য যে প্যাকেজটি লোড করার জন্য doy কিছু সময় নেয়।

library(Deducer)
microbenchmark(sortData(dd,c("z","b"),increasing= c(FALSE,TRUE)),times=1000)

Deducer লোড করা যায়নি। JGR কনসোল প্রয়োজন।

esort <- function(x, sortvar, ...) {
attach(x)
x <- x[with(x,order(sortvar,...)),]
return(x)
detach(x)
}

microbenchmark(esort(dd, -z, b),times=1000)

সংযুক্ত / বিচ্ছিন্নতার কারণে মাইক্রোবিনচার্কের সাথে সামঞ্জস্যপূর্ণ বলে মনে হচ্ছে না।

m <- microbenchmark(
  arrange(dd,desc(z),b),
  sort(dd, f= ~-z+b ),
  dd[with(dd, order(-z, b)), ] ,
  dd[order(-dd$z, dd$b),],
  times=1000
  )

uq <- function(x) { fivenum(x)[4]}  
lq <- function(x) { fivenum(x)[2]}

y_min <- 0 # min(by(m$time,m$expr,lq))
y_max <- max(by(m$time,m$expr,uq)) * 1.05

p <- ggplot(m,aes(x=expr,y=time)) + coord_cartesian(ylim = c( y_min , y_max )) 
p + stat_summary(fun.y=median,fun.ymin = lq, fun.ymax = uq, aes(fill=expr))

(লাইন নিম্ন চতুর্ভুজ থেকে উপরের চতুর্ভুজ পর্যন্ত প্রসারিত, বিন্দু মধ্যমা)

এই ফলাফল দেওয়া এবং সরলতা বনাম গতি গতি, আমি plyr প্যাকেজ arrange করার arrange দিতে হবে। এটি একটি সহজ সিনট্যাক্স এবং এখনও প্রায় দ্রুত হিসাবে বেস R তাদের দৃঢ় machinations সঙ্গে কমান্ড। সাধারণত উজ্জ্বল Hadley উইকহ্যাম কাজ। এটির সাথে আমার একমাত্র গোপনতা হল যে এটি স্ট্যান্ডার্ড R নামকরণকে ভেঙ্গে দেয় যেখানে বস্তুগুলি sort(object) দ্বারা sort(object) তবে আমি বুঝতে পারি কেন উপরে বর্ণিত প্রশ্নগুলিতে আলোচিত বিষয়গুলির কারণে হ্যডলি এমনভাবে করেছেন।


Dirk এর উত্তর মহান। এটি data.table s এবং data.table গুলি সূচকের জন্য ব্যবহৃত সিনট্যাক্সের মধ্যে একটি কী পার্থক্য তুলে ধরে।

## The data.frame way
dd[with(dd, order(-z, b)), ]

## The data.table way: (7 fewer characters, but that's not the important bit)
dd[order(-z, b)]

দুটি কলগুলির মধ্যে পার্থক্যটি ছোট, তবে এর গুরুত্বপূর্ণ ফলাফল হতে পারে। বিশেষ করে যদি আপনি উত্পাদন কোডটি লিখেন এবং / অথবা আপনার গবেষণায় সঠিকতা নিয়ে উদ্বিগ্ন হন, তবে পরিবর্তনশীল নামের অপ্রয়োজনীয় পুনরাবৃত্তি এড়ানোর জন্য এটি সর্বোত্তম। data.table আপনি এই কাজ করতে সাহায্য করে।

পরিবর্তনশীল নামগুলির পুনরাবৃত্তি আপনাকে কীভাবে সমস্যার সম্মুখীন হতে পারে তা এখানে একটি উদাহরণ:

আসুন Dirk এর উত্তর থেকে প্রসঙ্গ পরিবর্তন করি, এবং বলুন এটি একটি বড় প্রকল্পের অংশ যেখানে অনেকগুলি বস্তুর নাম রয়েছে এবং তারা দীর্ঘ এবং অর্থবহ; পরিবর্তে dd এটি quarterlyreport বলা quarterlyreport । এটা হতে পারে :

quarterlyreport[with(quarterlyreport,order(-z,b)),]

আচ্ছা ঠিক আছে. যে সঙ্গে কিছুই ভুল। তারপরে আপনার বস আপনাকে রিপোর্টে শেষ চতুর্থাংশের প্রতিবেদনটি অন্তর্ভুক্ত করতে বলে। আপনি আপনার কোডটি দিয়ে যান, বিভিন্ন স্থানে এবং শেষ পর্যন্ত কোনও বস্তু (পৃথিবীতে কীভাবে?) এর সাথে একটি অবজেক্ট যোগ করেছেন:

quarterlyreport[with(lastquarterlyreport,order(-z,b)),]

আপনি যা বোঝাতে চেয়েছেন তা নয় কিন্তু আপনি এটি স্পট করেননি কারণ আপনি এটি দ্রুত করেছিলেন এবং এটি একই কোডের পৃষ্ঠায় নেমে গেছে। কোডটি পড়ে না (কোনও সতর্কতা এবং কোনও ত্রুটি নেই) কারণ R মনে করে আপনি এটি বোঝেন। আপনি যে কেউ আপনার রিপোর্ট পড়তে আশা করি এটি স্পট, কিন্তু সম্ভবত তারা না। আপনি প্রোগ্রামিং ভাষা সঙ্গে অনেক কাজ করলে এই পরিস্থিতি সব পরিচিত হতে পারে। এটি একটি "টাইপো" আপনি বলতে হবে। আমি আপনার বসকে বলব "টাইপো" ঠিক করব।

তথ্য. data.table আমরা এই মত ক্ষুদ্র বিবরণ সম্পর্কে উদ্বিগ্ন। তাই আমরা পরিবর্তনশীল নাম টাইপ এড়াতে কিছু সহজ কাজ করেছি। কিছু খুব সহজ। i ইতিমধ্যে স্বয়ংক্রিয়ভাবে dd ফ্রেম মধ্যে মূল্যায়ন করা হয়। আপনি with() সব with() প্রয়োজন with() না।

পরিবর্তে

dd[with(dd, order(-z, b)), ]

এটা শুধু

dd[order(-z, b)]

এবং পরিবর্তে

quarterlyreport[with(lastquarterlyreport,order(-z,b)),]

এটা শুধু

quarterlyreport[order(-z,b)]

এটি একটি খুব ছোট পার্থক্য, তবে এটি কেবল একদিন আপনার গলাটি সংরক্ষণ করতে পারে। এই প্রশ্নের বিভিন্ন উত্তরগুলি তোলার সময়, ভেরিয়েবল নামগুলির পুনরাবৃত্তিগুলি নির্ধারণের মধ্যে আপনার মানদণ্ডের একটি হিসাবে গণনা বিবেচনা করুন। কিছু উত্তর বেশ কয়েকটি পুনরাবৃত্তি আছে, অন্যদের কেউ আছে।


Dplayer মধ্যে ব্যবস্থা () আমার প্রিয় বিকল্প। পাইপ অপারেটর ব্যবহার করুন এবং অন্তত গুরুত্বপূর্ণ থেকে সবচেয়ে গুরুত্বপূর্ণ দৃষ্টিভঙ্গি যান

dd1 <- dd %>%
    arrange(z) %>%
    arrange(desc(x))

অথবা আপনি প্যাকেজ doby ব্যবহার করতে পারেন

library(doBy)
dd <- orderBy(~-z+b, data=dd)

আপনি অ্যাড-অন সরঞ্জামগুলি ব্যবহার না করেই সরাসরি order() ফাংশনটি ব্যবহার করতে পারেন - এই সরল উত্তরটি দেখুন যা example(order) কোডের উপরে থেকে সরাসরি একটি কৌশল ব্যবহার করে:

R> dd[with(dd, order(-z, b)), ]
    b x y z
4 Low C 9 2
2 Med D 3 1
1  Hi A 8 1
3  Hi A 9 1

কিছু 2+ বছর পরে সম্পাদনা করুন: কলাম সূচক দ্বারা এটি কীভাবে করা যায় তা বলা হয়েছিল। উত্তরটি order() অনুসারে order() গুলি) অনুসারে order() ফাংশনটি পাস করতে হয়:

R> dd[order(-dd[,4], dd[,1]), ]
    b x y z
4 Low C 9 2
2 Med D 3 1
1  Hi A 8 1
3  Hi A 9 1
R> 

কলামের নাম (এবং সহজে / আরও সরাসরি অ্যাক্সেসের জন্য with() ব্যবহার করার পরিবর্তে।


আমি এন কলামগুলির জন্য আমার ক্রম প্রক্রিয়াটি স্বয়ংক্রিয়ভাবে চালু করতে চাইলে উপরের সমাধানগুলির সাথে সংগ্রাম করছিলাম, যার কলামের নাম প্রতিটি সময় আলাদা হতে পারে। আমি সোজা প্যাকেজে এটি করার জন্য মন প্যাকেজ থেকে একটি সুপার সহায়ক ফাংশন খুঁজে পেয়েছি:

dfOrder(myDf, columnIndices)

যেখানে কলাম সূচকগুলি এক বা একাধিক কলামের সূচক, যাতে আপনি তাদের ক্রম করতে চান। এখানে আরো তথ্য:

dfOrder 'মনো' প্যাকেজ থেকে ফাংশন


আর প্যাকেজ data.table . table একটি সহজতর সিনট্যাক্স সহ ডেটা . tables এর দ্রুতমেমরি দক্ষ ক্রম প্রদান করে (একটি অংশ যা ম্যাট তার উত্তরে বেশ চমকপ্রদভাবে তুলে ধরেছে)। বেশিরভাগ উন্নতি হয়েছে এবং setorder() একটি নতুন ফাংশন setorder() রয়েছে। v1.9.5+ থেকে, setorder() এছাড়াও setorder() দিয়ে কাজ করে।

প্রথমত, আমরা অন্যান্য উত্তর থেকে উল্লিখিত বিভিন্ন পদ্ধতির একটি ডেটা সেট তৈরি করব এবং তারপরে ডেটা . table এর বৈশিষ্ট্যগুলি তালিকাভুক্ত করব

ডেটা:

require(plyr)
require(doBy)
require(data.table)
require(dplyr)
require(taRifx)

set.seed(45L)
dat = data.frame(b = as.factor(sample(c("Hi", "Med", "Low"), 1e8, TRUE)),
                 x = sample(c("A", "D", "C"), 1e8, TRUE),
                 y = sample(100, 1e8, TRUE),
                 z = sample(5, 1e8, TRUE), 
                 stringsAsFactors = FALSE)

benchmarks:

রিপোর্ট করা সময়গুলি চলমান system.time(...) থেকে। সময় system.time(...) নীচের দেখানো এই ফাংশন। সময় নীচে নিযুক্ত করা হয় (ধীর গতির থেকে দ্রুততম)।

orderBy( ~ -z + b, data = dat)     ## doBy
plyr::arrange(dat, desc(z), b)     ## plyr
arrange(dat, desc(z), b)           ## dplyr
sort(dat, f = ~ -z + b)            ## taRifx
dat[with(dat, order(-z, b)), ]     ## base R

# convert to data.table, by reference
setDT(dat)

dat[order(-z, b)]                  ## data.table, base R like syntax
setorder(dat, -z, b)               ## data.table, using setorder()
                                   ## setorder() now also works with data.frames 

# R-session memory usage (BEFORE) = ~2GB (size of 'dat')
# ------------------------------------------------------------
# Package      function    Time (s)  Peak memory   Memory used
# ------------------------------------------------------------
# doBy          orderBy      409.7        6.7 GB        4.7 GB
# taRifx           sort      400.8        6.7 GB        4.7 GB
# plyr          arrange      318.8        5.6 GB        3.6 GB 
# base R          order      299.0        5.6 GB        3.6 GB
# dplyr         arrange       62.7        4.2 GB        2.2 GB
# ------------------------------------------------------------
# data.table      order        6.2        4.2 GB        2.2 GB
# data.table   setorder        4.5        2.4 GB        0.4 GB
# ------------------------------------------------------------
  • data.table এর DT[order(...)] সিনট্যাক্স অন্যান্য পদ্ধতির দ্রুততম (10 dplyr ) এর চেয়ে দ্রুত 10x দ্রুত, একই রকম পরিমাণ মেমরি dplyr হিসাবে dplyr

  • data.table এর setorder() অন্যান্য পদ্ধতিগুলির দ্রুততম ( dplyr ) চেয়ে দ্রুত ছিল, যা dplyr গিগাবাইট অতিরিক্ত মেমরি গ্রহণ করেdat এখন আমাদের প্রয়োজন অনুসারে (এটি রেফারেন্স দ্বারা আপডেট করা হয়)।

তথ্য.table বৈশিষ্ট্য:

গতি:

  • data.table এর ক্রম অত্যন্ত দ্রুত কারণ এটি রডিক্স ক্রম প্রয়োগ করে।

  • সিনট্যাক্স DT[order(...)] ডেটা.table এর দ্রুত ক্রম ব্যবহারের জন্য অভ্যন্তরীণভাবে অপ্টিমাইজ করা হয়েছে। আপনি পরিচিত বেস আর সিনট্যাক্স ব্যবহার চালিয়ে যেতে পারেন তবে প্রক্রিয়াটি গতি বাড়ান (এবং কম মেমরি ব্যবহার করুন)।

স্মৃতি:

  • বেশিরভাগ সময়ে, আমাদের পুনরায় তথ্য দেওয়ার পরে মূল তথ্য। ফ্রেম বা ডেটা . table প্রয়োজন হয় না। অর্থাৎ, আমরা সাধারণত একই বস্তুর ফলাফলটি বরাদ্দ করি, উদাহরণস্বরূপ:

    DF <- DF[order(...)]

    সমস্যাটি মূল বস্তুর অন্তত দুবার (2x) মেমরির প্রয়োজন। মেমরি দক্ষ হতে, ডেটা.table এছাড়াও একটি ফাংশন setorder()

    setorder() কোনও অতিরিক্ত কপি ছাড়াই by reference ( ইন-স্থান ) by reference tables reorders । এটি শুধুমাত্র একটি কলাম আকার সমান অতিরিক্ত মেমরি ব্যবহার করে।

অন্যান্য বৈশিষ্ট্য:

  1. এটি integer , logical , numeric , character এবং এমনকি bit64::integer64 ধরনের সমর্থন করে।

    উল্লেখ্য যে factor , Date , POSIXct ইত্যাদি .. ক্লাস অতিরিক্ত গুণাবলী সহ সব integer / numeric ধরনের এবং সেইসাথে সমর্থিত হয়।

  2. ভিত্তি R তে, আমরা ব্যবহার করতে পারি না - ক্রম অনুসারে ক্রম অনুসারে সাজানোর জন্য একটি চরিত্র ভেক্টরের উপর। পরিবর্তে আমাদের -xtfrm(.) ব্যবহার করতে হবে।

    যাইহোক, ডেটা . table , আমরা শুধু উদাহরণস্বরূপ, করতে পারেন dat[order(-x)] বা setorder(dat, -x)


আরেকটি বিকল্প, rgr প্যাকেজ ব্যবহার করে:

> library(rgr)
> gx.sort.df(dd, ~ -z+b)
    b x y z
4 Low C 9 2
2 Med D 3 1
1  Hi A 8 1
3  Hi A 9 1

এসকিউএল স্বাভাবিকভাবে আপনার কাছে আসে, sqldf উদ্দেশ্যে কোডড হিসাবে অর্ডারে পরিচালনা করে।


ধরুন আপনার কাছে একটি data.frame A এবং আপনি x কমান্ডিং নামক কলাম ব্যবহার করে এটি বাছাই করতে চান। সাজানো তথ্য newdata কল করুন

newdata <- A[order(-A$x),]

আপনি যদি ঊর্ধ্বমুখী ক্রম চান তবে "-" সাথে প্রতিস্থাপন করুন। আপনি কিছু ভালো হতে পারে

newdata <- A[order(-A$x, A$y, -A$z),]

যেখানে x এবং z data.frame A কিছু কলাম রয়েছে। এর মানে হল ক্রমবর্ধমান data.frame x descending, y ascending এবং z descending।


বিকল্পভাবে, প্যাকেজ Deducer ব্যবহার করে

library(Deducer)
dd<- sortData(dd,c("z","b"),increasing= c(FALSE,TRUE))

সম্পূর্ণতার জন্য: আপনি BBmisc প্যাকেজ থেকে sortByCol() ফাংশন ব্যবহার করতে পারেন:

library(BBmisc)
sortByCol(dd, c("z", "b"), asc = c(FALSE, TRUE))
    b x y z
4 Low C 9 2
2 Med D 3 1
1  Hi A 8 1
3  Hi A 9 1

কর্মক্ষমতা তুলনা:

library(microbenchmark)
microbenchmark(sortByCol(dd, c("z", "b"), asc = c(FALSE, TRUE)), times = 100000)
median 202.878

library(plyr)
microbenchmark(arrange(dd,desc(z),b),times=100000)
median 148.758

microbenchmark(dd[with(dd, order(-z, b)), ], times = 100000)
median 115.872




r-faq