সনাক্তকারী দ্বারা গোষ্ঠীভুক্ত ডেটা ফ্রেমের প্রথম সারিটি পাওয়ার জন্য আরে দ্রুত উপায়গুলি [বন্ধ]


14

কখনও কখনও আমাকে কোনও সনাক্তকারী দ্বারা গোষ্ঠীযুক্ত ডেটা সেট করার প্রথম সারিটি পাওয়া দরকার, যেমন পৃথকভাবে একাধিক পর্যবেক্ষণ থাকে যখন বয়স এবং লিঙ্গ পুনরুদ্ধার করার সময়। আর-তে এটি করার একটি দ্রুত (বা দ্রুততম) উপায় কী? আমি নীচে সামগ্রিক () ব্যবহার করেছি এবং সন্দেহ করি এর আরও ভাল উপায় আছে। এই প্রশ্নটি পোস্ট করার আগে আমি গুগলে কিছুটা অনুসন্ধান করেছি, খুঁজে পেয়েছি এবং ddply চেষ্টা করেছি, এবং অবাক হয়ে গিয়েছিলাম যে এটি অত্যন্ত ধীর এবং আমার ডেটাসেটে (400,000 সারি x 16 কলস, 7,000 অনন্য আইডি) মেমরির ত্রুটি দিয়েছে, যেখানে সমষ্টিগত () সংস্করণ রয়েছে যুক্তিসঙ্গত দ্রুত ছিল।

(dx <- data.frame(ID = factor(c(1,1,2,2,3,3)), AGE = c(30,30,40,40,35,35), FEM = factor(c(1,1,0,0,1,1))))
# ID AGE FEM
#  1  30   1
#  1  30   1
#  2  40   0
#  2  40   0
#  3  35   1
#  3  35   1
ag <- data.frame(ID=levels(dx$ID))
ag <- merge(ag, aggregate(AGE ~ ID, data=dx, function(x) x[1]), "ID")
ag <- merge(ag, aggregate(FEM ~ ID, data=dx, function(x) x[1]), "ID")
ag
# ID AGE FEM
#  1  30   1
#  2  40   0
#  3  35   1
#same result:
library(plyr)
ddply(.data = dx, .var = c("ID"), .fun = function(x) x[1,])

আপডেট: চেসের উত্তর এবং ম্যাট পার্কারের মন্তব্য দেখুন যা আমি সবচেয়ে মার্জিত পদ্ধতির হিসাবে বিবেচনা করি। data.tableপ্যাকেজটি ব্যবহার করে দ্রুততম সমাধানের জন্য @ ম্যাথু ডাওলের উত্তর দেখুন ।


আপনার সমস্ত উত্তরের জন্য ধন্যবাদ। @ স্টিভের ডেটা.ট্যাবল সমাধানটি আমার কাছে @ গ্যাভিনের সমষ্টি () সমাধানের উপর সেট করা ডেটাতে ~ 5 এর একটি ফ্যাক্টর দ্বারা দ্রুততম ছিল (যা আমার সামগ্রিক () কোডের চেয়ে দ্রুত ছিল) এবং .5 7.5 এর একটি ফ্যাক্টর @ ম্যাট এর বাই () সমাধানের উপরে। আমি পুনর্নির্মাণের আইডিয়াকে সময় দিইনি কারণ আমি এটি দ্রুত কাজ করতে পারি না। আমি অনুমান করছি যে @ চেসে প্রদত্ত সমাধানটি সবচেয়ে দ্রুত হবে এবং এটি আসলে আমি যা খুঁজছিলাম তা ছিল তবে আমি যখন এই মন্তব্যটি লিখতে শুরু করি তখন কোডটি কাজ করে না (আমি এখন এটি ঠিক করেছি!)।
লক অফফ

প্রকৃতপক্ষে @ চেসটি ডেটা.ট্যাবলের চেয়ে ~ 9 এর ফ্যাক্টর দ্বারা দ্রুততর ছিল, তাই আমি আমার গৃহীত উত্তর পরিবর্তন করেছি। সবাইকে আবার ধন্যবাদ - নতুন সরঞ্জামের একটি গোছা শিখেছি।
লকঅফ অফ

দুঃখিত, আমি আমার কোড ঠিক করেছি। এখানে একটি সতর্কতা বা কৌশলটি এমন কোনও মানকে বোঝানো যা আপনার আইডির একটি নয় যা diff()যাতে আপনি প্রথম আইডিটি বেছে নিতে পারেন dx
তাড়া 18

উত্তর:


11

আপনার আইডি কলামটি কি আসলেই একটি ফ্যাক্টর? যদি এটি আসলে সংখ্যাসূচক হয় তবে আমি মনে করি আপনি diffনিজের সুবিধার জন্য ফাংশনটি ব্যবহার করতে পারেন । আপনি এটি সংখ্যার সাথে জোর করেও করতে পারেন as.numeric()

dx <- data.frame(
    ID = sort(sample(1:7000, 400000, TRUE))
    , AGE = sample(18:65, 400000, TRUE)
    , FEM = sample(0:1, 400000, TRUE)
)

dx[ diff(c(0,dx$ID)) != 0, ]

1
চতুর! আপনি dx[c(TRUE, dx$ID[-1] != dx$ID[-length(dx$ID)], ]অ-সংখ্যাসূচক ডেটাও করতে পারেন - আমি চরিত্রের জন্য 0.03 পাই, কারণগুলির জন্য 0.05 পাই। পিএস: দ্বিতীয় শূন্যের পরে )আপনার প্রথম system.time()ফাংশনে অতিরিক্ত রয়েছে ।
ম্যাট পার্কার

@ ম্যাট - ভাল কল এবং দুর্দান্ত ধরা। আমি আজ একটি ফ্লিপ মূল্যের কোড অনুলিপি / পেস্ট করতে সক্ষম হতে দেখছি না।
তাড়াতাড়ি

আমি লন্ডন সাইকেল ভাড়া ভাড়া প্রকল্পে কাজ করছি এবং ব্যবহারকারীর বাইক ভাড়া নেওয়ার প্রথম এবং শেষ উদাহরণ খুঁজে পাওয়ার কোনও উপায় খুঁজে পাওয়া দরকার। 1 মিলিয়ন ব্যবহারকারী, প্রতি বছরে 10 মিলিয়ন ট্রিপ এবং কয়েক বছরের ডেটা সহ আমার "ফর" লুপটি প্রতি সেকেন্ডে 1 জন ব্যবহারকারী করছিল। আমি "বাই" সমাধানটি চেষ্টা করেছিলাম এবং এটি এক ঘন্টা পরেও শেষ করতে ব্যর্থ হয়েছিল। "ম্যাট পার্কারের চেজ এর সমাধানের বিকল্প" কী করছে তা প্রথমে আমি বুঝতে পারি না, তবে শেষ পর্যন্ত পেনিসটি নেমে যায় এবং এটি কয়েক সেকেন্ডের মধ্যেই কার্যকর হয়ে যায়। সুতরাং বৃহত্তর ডেটাসেটের সাহায্যে উন্নতি সম্পর্কে আরও বড় বিষয়টি আমার অভিজ্ঞতার দ্বারা প্রমাণিত।
জর্জ সিম্পসন

@ জর্জিসিম্পসন - এটি এখনও উল্লেখ করা হচ্ছে দেখে খুশি! data.tableসমাধান নিচে নিচে তাই আমি (এটা সম্ভবত গৃহীত উত্তর এখানে থাকা উচিত) যে খুঁজে বার করো চাই যদি আমি ছিল, দ্রুততম হতে প্রমাণ করা উচিত নয়।
চেজ

17

স্টিভের জবাব অবধি অনুসরণ করে ডেটা.ট্যাবেলে আরও দ্রুততর উপায় রয়েছে:

> # Preamble
> dx <- data.frame(
+     ID = sort(sample(1:7000, 400000, TRUE))
+     , AGE = sample(18:65, 400000, TRUE)
+     , FEM = sample(0:1, 400000, TRUE)
+ )
> dxt <- data.table(dx, key='ID')

> # fast self join
> system.time(ans2<-dxt[J(unique(ID)),mult="first"])
 user  system elapsed 
0.048   0.016   0.064

> # slower using .SD
> system.time(ans1<-dxt[, .SD[1], by=ID])
  user  system elapsed 
14.209   0.012  14.281 

> mapply(identical,ans1,ans2)  # ans1 is keyed but ans2 isn't, otherwise identical
  ID  AGE  FEM 
TRUE TRUE TRUE 

আপনার যদি কেবল প্রতিটি গ্রুপের প্রথম সারির প্রয়োজন হয় তবে সরাসরি সেই সারিতে যোগ দেওয়া আরও দ্রুত। কেন প্রতিবার .SD অবজেক্ট তৈরি করবেন, কেবল এটির প্রথম সারিটি ব্যবহার করার জন্য?

"চেসের সমাধানের জন্য ম্যাট পার্কারের বিকল্প" (যা এখন পর্যন্ত সবচেয়ে দ্রুত বলে মনে হয়েছিল) এর সাথে 0.04 ডেটা তুলনা করুন:

> system.time(ans3<-dxt[c(TRUE, dxt$ID[-1] != dxt$ID[-length(dxt$ID)]), ])
 user  system elapsed 
0.284   0.028   0.310 
> identical(ans1,ans3)
[1] TRUE 

সুতরাং 5 গুন দ্রুত, তবে এটি 1 মিলিয়ন সারি নীচে একটি ছোট টেবিল। আকার বাড়ার সাথে সাথে তফাতও বাড়ায়।


বাহ, [.data.tableফাংশনটি কীভাবে "স্মার্ট" হতে পারে তা আমি সত্যিই প্রশংসা করি নি ... আমার ধারণা আমি যদি বুঝতে পারি না যে আপনি .SDযদি সত্যিই এটির প্রয়োজন না হন তবে আপনি কোনও বস্তু তৈরি করেন নি। সুন্দর!
স্টিভ লিয়ানোগ্লো

হ্যাঁ, এটা সত্যিই দ্রুত! এমনকি আপনি যদি dxt <- data.table(dx, key='ID')কলটিতে সিস্টেম.টাইম () এ অন্তর্ভুক্ত থাকেন তবে এটি @ ম্যাট এর সমাধানের চেয়ে দ্রুত।
লকডফ

আমার ধারণা এখন এই পুরানো ইতিহাসটি নতুন ডেটাগুলির মতো able টেবিল সংস্করণগুলি SD[1L]সম্পূর্ণরূপে অনুকূলিত হয়েছিল এবং আসলে @ স্টিভিলিয়ানোগ্লু উত্তরটি 5e7 সারিগুলির দ্বিগুণ দ্রুত হবে।
ডেভিড আরেনবুর্গ

@ ডেভিড আরেনবার্গে v1.9.8 নভেম্বর 2016 থেকে হ্যাঁ। এই উত্তরটি সরাসরি সম্পাদনা করতে নির্দ্বিধায় বা সম্ভবত এই প্রশ্নটির সম্প্রদায় উইকি বা কিছু হতে পারে।
ম্যাট ডওল

10

আপনার একাধিক merge()পদক্ষেপের দরকার নেই , কেবল aggregate()আগ্রহের দুটি পরিবর্তনশীল:

> aggregate(dx[, -1], by = list(ID = dx$ID), head, 1)
  ID AGE FEM
1  1  30   1
2  2  40   0
3  3  35   1

> system.time(replicate(1000, aggregate(dx[, -1], by = list(ID = dx$ID), 
+                                       head, 1)))
   user  system elapsed 
  2.531   0.007   2.547 
> system.time(replicate(1000, {ag <- data.frame(ID=levels(dx$ID))
+ ag <- merge(ag, aggregate(AGE ~ ID, data=dx, function(x) x[1]), "ID")
+ ag <- merge(ag, aggregate(FEM ~ ID, data=dx, function(x) x[1]), "ID")
+ }))
   user  system elapsed 
  9.264   0.009   9.301

তুলনার সময়:

1) ম্যাট এর সমাধান:

> system.time(replicate(1000, {
+ agg <- by(dx, dx$ID, FUN = function(x) x[1, ])
+ # Which returns a list that you can then convert into a data.frame thusly:
+ do.call(rbind, agg)
+ }))
   user  system elapsed 
  3.759   0.007   3.785

2) জাচের পুনরায় আকার 2 সমাধান:

> system.time(replicate(1000, {
+ dx <- melt(dx,id=c('ID','FEM'))
+ dcast(dx,ID+FEM~variable,fun.aggregate=mean)
+ }))
   user  system elapsed 
 12.804   0.032  13.019

3) স্টিভ এর ডেটা। টেবিল সমাধান:

> system.time(replicate(1000, {
+ dxt <- data.table(dx, key='ID')
+ dxt[, .SD[1,], by=ID]
+ }))
   user  system elapsed 
  5.484   0.020   5.608 
> dxt <- data.table(dx, key='ID') ## one time step
> system.time(replicate(1000, {
+ dxt[, .SD[1,], by=ID] ## try this one line on own
+ }))
   user  system elapsed 
  3.743   0.006   3.784

4) চেসের দ্রুত সমাধানটি সংখ্যক ব্যবহার করে, গুণক নয় ID,:

> dx2 <- within(dx, ID <- as.numeric(ID))
> system.time(replicate(1000, {
+ dy <- dx[order(dx$ID),]
+ dy[ diff(c(0,dy$ID)) != 0, ]
+ }))
   user  system elapsed 
  0.663   0.000   0.663

এবং 5) ম্যাট পার্কারের চেসের সমাধানের বিকল্প, চরিত্র বা ফ্যাক্টরের জন্য ID, যা চেসের সংখ্যার চেয়ে কিছুটা দ্রুত ID:

> system.time(replicate(1000, {
+ dx[c(TRUE, dx$ID[-1] != dx$ID[-length(dx$ID)]), ]
+ }))
   user  system elapsed 
  0.513   0.000   0.516

ওহ, ঠিক আছে, ধন্যবাদ! সমষ্টি জন্য সিনট্যাক্স সম্পর্কে ভুলে গেছেন।
লক অফফ

আপনি যদি চেসের সমাধানটি যুক্ত করতে চান তবে আমি যা পেয়েছি তা এখানে:dx$ID <- sample(as.numeric(dx$ID)) #assuming IDs arent presorted system.time(replicate(1000, { dy <- dx[order(dx$ID),] dy[ diff(c(0,dy$ID)) != 0, ] })) user system elapsed 0.58 0.00 0.58
লকডফ করুন

@ লকডঅফ - সম্পন্ন হয়েছে, ধন্যবাদ, তবে আমি এলোমেলোভাবে এসগুলির নমুনা করিনি IDযাতে ফলাফল অন্যান্য সমাধানের সাথে তুলনীয় হয়।
মনিকা পুনরায় ইনস্টল করুন - জি সিম্পসন

এবং সময় @ চ্যাট এর উত্তরের মন্তব্যে @ ম্যাট পার্কারের সংস্করণ
মনিকা

2
সময়গুলি করার জন্য ধন্যবাদ, গ্যাভিন - এটি এই জাতীয় প্রশ্নের জন্য সত্যই সহায়ক।
ম্যাট পার্কার

10

আপনি ডেটা টেবিল প্যাকেজটি ব্যবহার করার চেষ্টা করতে পারেন ।

আপনার নির্দিষ্ট ক্ষেত্রে, উল্টোটি এটি (উন্মাদ) দ্রুত। প্রথমবার এটির সাথে পরিচয় হওয়ার পরে, আমি কয়েক হাজার সারি সহ ডেটা.ফ্রেম অবজেক্টগুলিতে কাজ করছিলাম। "সাধারন" aggregateবা ddplyপদ্ধতিগুলি শেষ করতে ~ 1-2 মিনিট নেওয়া হয়েছিল (হ্যাডলি idata.frameমোজোর সাথে পরিচয় করার আগে এটি ছিল ddply)। ব্যবহার করে data.table, অপারেশনটি আক্ষরিকভাবে কয়েক সেকেন্ডের মধ্যে সম্পন্ন হয়েছিল।

খারাপ দিকটি এটি এত দ্রুত কারণ এটি "কী কলামগুলি" দ্বারা আপনার ডেটা.টিবেল (এটি একটি ডেটাফ্রেমের মতো) রিসর্ট করবে এবং আপনার ডেটার উপগ্রহগুলি সন্ধান করতে একটি স্মার্ট অনুসন্ধান কৌশল ব্যবহার করবে। এটির পরিসংখ্যান সংগ্রহ করার আগে এটি আপনার ডেটার পুনঃক্রমের ফলাফল করবে।

প্রদত্ত যে আপনি কেবল প্রতিটি গ্রুপের প্রথম সারিটি চাইবেন - সম্ভবত পুনঃক্রমনটি কোন গোলটিকে প্রথমে বিশৃঙ্খলা করবে, এ কারণেই এটি আপনার পরিস্থিতিতে উপযুক্ত নাও হতে পারে।

যাইহোক, আপনাকে data.tableএখানে উপযুক্ত কিনা তা বিচার করতে হবে , তবে আপনি উপস্থাপিত ডেটার সাথে আপনি এটি ব্যবহার করবেন:

install.packages('data.table') ## if yo udon't have it already
library(data.table)
dxt <- data.table(dx, key='ID')
dxt[, .SD[1,], by=ID]
     ID AGE FEM
[1,]  1  30   1
[2,]  2  40   0
[3,]  3  35   1

আপডেট: ম্যাথু ডাওল (ডেটা টেবিল প্যাকেজের মূল বিকাশকারী) এই সমস্যার সমাধান হিসাবে এখানে উত্তর হিসাবে সমাধান করতে ডেটা.ট্যাবিল ব্যবহার করার জন্য একটি আরও ভাল / স্মার্ট / (অত্যন্ত) আরও কার্যকর উপায় সরবরাহ করেছে ... অবশ্যই তা পরীক্ষা করে দেখুন ।


4

পুনরায় আকার 2 চেষ্টা করুন

library(reshape2)
dx <- melt(dx,id=c('ID','FEM'))
dcast(dx,ID+FEM~variable,fun.aggregate=mean)

3

আপনি চেষ্টা করতে পারেন

agg <- by(dx, dx$ID, FUN = function(x) x[1, ])
# Which returns a list that you can then convert into a data.frame thusly:
do.call(rbind, agg)

plyrযদিও এর চেয়ে দ্রুততর কিছু হবে কিনা আমার ধারণা নেই ।

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