কীভাবে দক্ষতার সাথে আর এর স্ট্রিংয়ে বাছাই করা যায়?


9

আমি কীভাবে দক্ষতার সাথে কোনও ভেক্টরে প্রতিটি স্ট্রিংয়ের অক্ষরকে বাছাই করতে পারি? উদাহরণস্বরূপ, স্ট্রিংয়ের একটি ভেক্টর দেওয়া:

set.seed(1)
strings <- c(do.call(paste0, replicate(4, sample(LETTERS, 10000, TRUE), FALSE)),
do.call(paste0, replicate(3, sample(LETTERS, 10000, TRUE), FALSE)),
do.call(paste0, replicate(2, sample(LETTERS, 10000, TRUE), FALSE)))

আমি একটি ফাংশন লিখেছি যা প্রতিটি স্ট্রিংকে ভেক্টরে বিভক্ত করবে, ভেক্টরকে বাছাই করবে এবং তারপরে আউটপুটটি সঙ্কুচিত করবে:

sort_cat <- function(strings){
  tmp <- strsplit(strings, split="")
  tmp <- lapply(tmp, sort)
  tmp <- lapply(tmp, paste0, collapse = "")
  tmp <- unlist(tmp)
  return(tmp)
}
sorted_strings <- sort_cat(strings)

তবে, স্ট্রিংয়ের ভেক্টরটি এটিতে প্রয়োগ করতে আমার খুব দীর্ঘ এবং এই ফাংশনটি খুব ধীর slow পারফরম্যান্স উন্নত করার জন্য কারও কি কোনও পরামর্শ আছে?


1
স্ট্রিং প্যাকেজটি দেখুন - এটি একটি স্পিডআপ বনাম বেস সরবরাহ করে। রিচ Scriven এর উত্তর আরও বিস্তারিত জানার দেয়: stackoverflow.com/questions/5904797/...
user2474226

lettersদৈর্ঘ্য তিন সবসময় আপনার উদাহরণ হিসাবে নয়, তারা?
jay.sf

না, স্ট্রিংগুলির দৈর্ঘ্য পৃথক হতে পারে।
পাওয়েজ

আমি মনে করি যোগ করেন যে fixed = TRUEstrsplit()কাজের উন্নতি ঘটবে যেমন Regex ব্যবহার জড়িত করা হবে না।
tmfmnk

উত্তর:


3

আপনি নিশ্চিতভাবে লুপের সংখ্যা হ্রাস করে সময় হ্রাস করতে পারেন, এবং আরও parallelপ্যাকেজটি ব্যবহার করে করুন ... আমার পদ্ধতিরটি একবার বিভক্ত স্ট্রিং হয়ে যাবে, তারপরে লুপ সাজানোর এবং পেস্ট করুন:

sort_cat <- function(strings){
    tmp <- strsplit(strings, split="")
    tmp <- lapply(tmp, sort)
    tmp <- lapply(tmp, paste0, collapse = "")
    tmp <- unlist(tmp)
    return(tmp)
}

sort_cat2 <- function(strings){
    unlist(mcMap(function(i){
        stri_join(sort(i), collapse = "")
    }, stri_split_regex(strings, "|", omit_empty = TRUE, simplify = F), mc.cores = 8L))
}

> microbenchmark::microbenchmark(
+     old = sort_cat(strings[1:500000]),
+     new = sort_cat2(strings[1:500000]),
+     times = 1
+ )
Unit: seconds
 expr        min         lq       mean     median         uq        max neval
  old 9.62673395 9.62673395 9.62673395 9.62673395 9.62673395 9.62673395     1
  new 5.10547437 5.10547437 5.10547437 5.10547437 5.10547437 5.10547437     1

4 সেকেন্ডের মতো শেভ করে তবে এটি এখনও তত দ্রুত নয় ...

সম্পাদন করা

ঠিক আছে apply.. কৌশলটি এখানে ব্যবহার করে নেমে গেছে:

1) বিভক্ত সীমানার চেয়ে চিঠিগুলি বের করুন 2) ফলাফলগুলি সহ একটি ম্যাট্রিক্স তৈরি করুন 3) সারি অনুসারে পুনরাবৃত্তি করুন 4) বাছাই করুন 5) যোগ দিন

আপনি একাধিক লুপ এবং তালিকাভুক্তি এড়ান .... IGNORE:? সাবধানতা যদি বিভিন্ন দৈর্ঘ্যের স্ট্রিং থাকে তবে আপনাকে কোনও খালি বা এনএ applyযেমন এর মধ্যে সরিয়ে ফেলতে হবেi[!is.na(i) && nchar(i) > 0]

sort_cat3 <- function(strings){
    apply(stri_extract_all_regex(strings, "\\p{L}", simplify = TRUE), 1, function(i){
        stri_join(stri_sort(i), collapse = "")
    })
}

> microbenchmark::microbenchmark(
+     old = sort_cat(strings[1:500000]),
+     mapping = sort_cat2(strings[1:500000]),
+     applying = sort_cat3(strings[1:500000]),
+     times = 1
+ )
Unit: seconds
     expr         min          lq        mean      median          uq         max neval
      old 10.35101934 10.35101934 10.35101934 10.35101934 10.35101934 10.35101934     1
  mapping  5.12771799  5.12771799  5.12771799  5.12771799  5.12771799  5.12771799     1
 applying  3.97775326  3.97775326  3.97775326  3.97775326  3.97775326  3.97775326     1

আমাদের 10.3 সেকেন্ড থেকে 3.98 এ নিয়ে যায়


আপনি যদি সমান্তরালভাবে মূল ফাংশনটি চালান তবে স্পিডআপটি কী?
স্লাভা-কোহুত

50% এর কিছুটা কমিয়ে আনা হয়েছে। tmp <- strsplit(strings, split="") unlist(mclapply(tmp, function(i){ paste0(sort(i), collapse = "") }))
কার্ল বোনারি

@ গ্রেগর এটি করে। শুধু পরীক্ষা এবং প্রদর্শিত হবে?
কার্ল বোনারি

দুর্দান্ত, কেবল যাচাই করা হয়েছে :)
গ্রেগর টমাস

না মোটেও না .. পুরোপুরি নিজেই আমার একই প্রশ্ন ছিল .. যার অর্থ এনএ / খালি মুছে ফেলার বিষয়ে আমি যে নোটটি রেখেছি তা বাদ দিন ... এটির দরকার নেই। stringiসুদূর লোকের দ্বারা আমার প্রিয় প্যাকেজটি ...
কার্ল বোনেরি

4

ব্যবহার করে পুনরায় বাস্তবায়ন stringiমোটামুটি 4x স্পিডআপ দেয়। আমিও সম্পাদিত sort_catব্যবহারের fixed = TRUEমধ্যে strsplit, যা এটা তোলে একটি সামান্য দ্রুত। এবং কার্লকে একক লুপ পরামর্শের জন্য ধন্যবাদ, যা আমাদের আরও কিছুটা গতি বাড়িয়ে দেয়।

sort_cat <- function(strings){
  tmp <- strsplit(strings, split="", fixed = TRUE)
  tmp <- lapply(tmp, sort)
  tmp <- lapply(tmp, paste0, collapse = "")
  tmp <- unlist(tmp)
  return(tmp)
}

library(stringi)
sort_stringi = function(s) {
  s = stri_split_boundaries(s, type = "character")
  s = lapply(s, stri_sort)
  s = lapply(s, stri_join, collapse = "")
  unlist(s)
}

sort_stringi_loop = function(s) {
  s = stri_split_boundaries(s, type = "character")
  for (i in seq_along(s)) {
    s[[i]] = stri_join(stri_sort(s[[i]]), collapse = "")
  }
  unlist(s)
}

bench::mark(
  sort_cat(strings),
  sort_stringi(strings),
  sort_stringi_loop(strings)
)
# # A tibble: 3 x 13
#   expression                    min median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc total_time result memory
#   <bch:expr>                 <bch:> <bch:>     <dbl> <bch:byt>    <dbl> <int> <dbl>   <bch:tm> <list> <list>
# 1 sort_cat(strings)          23.01s 23.01s    0.0435    31.2MB     2.17     1    50     23.01s <chr ~ <Rpro~
# 2 sort_stringi(strings)       6.16s  6.16s    0.162     30.5MB     2.11     1    13      6.16s <chr ~ <Rpro~
# 3 sort_stringi_loop(strings)  5.75s  5.75s    0.174     15.3MB     1.74     1    10      5.75s <chr ~ <Rpro~
# # ... with 2 more variables: time <list>, gc <list>

এই পদ্ধতিটি সমান্তরালেও ব্যবহার করা যেতে পারে। আপনি আরও দ্রুত যেতে চাইলে কোন ক্রিয়াকলাপগুলি আসলে সবচেয়ে দীর্ঘায়িত হয় তা দেখার জন্য কোডটি রচনা করা ভাল পরবর্তী পদক্ষেপ হবে।


1
আমি মনে করি এটি প্রয়োগের চেয়ে দ্রুত শেষ হবে এবং বিভিন্ন দৈর্ঘ্য হলে খালি মানগুলি মুছে ফেলার উপর নির্ভর করবে না। তালিকাভুক্ত মোড়ানো একটি লুপ প্রস্তাব দিতে পারে, যদিও?
কার্ল বোনারি

1
একক লুপ গতি আরও কিছুটা আরও উন্নত করে, ধন্যবাদ!
গ্রেগর টমাস

হ্যাঁ মানুষ। যদিও এটি এখনও আমাকে বাগিয়ে দিচ্ছে। আমি এই পুরো জিনিসটি করার মতো খুব স্পষ্ট এবং সহজ
উপায়টি

আমার অর্থ, কোনও আরসিপিপি ফাংশন লিখতে সম্ভবত এটি বেশ সহজ হবে যা কেবল এটি করে এবং দ্রুত বজ্রপাত হবে। তবে আর এর মধ্যে কাজ করে, আমি মনে করি আমরা মূলত এই পদক্ষেপগুলি সীমাবদ্ধ করছি।
গ্রেগর টমাস

এটাই আমি ভাবছিলাম: সি ++
কার্ল বোনেরি

1

এই সংস্করণটি কিছুটা দ্রুত

sort_cat2=function(strings){
A=matrix(unlist(strsplit(strings,split="")),ncol=3,byrow=TRUE)
B=t(apply(A,1,sort))
paste0(B[,1],B[,2],B[,3])
}

তবে আমি মনে করি এটি অনুকূলিত হতে পারে


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