2015-10-04 8 views
7

मैं स्कैला सूची या सरणी (आरडीडी नहीं) से यादृच्छिक रूप से नमूना करना चाहता हूं, नमूना आकार सूची या सरणी की लंबाई से काफी लंबा हो सकता है, मैं यह कुशलता से कैसे कर सकता हूं? क्योंकि नमूना आकार बहुत बड़ा हो सकता है और नमूनाकरण (विभिन्न सूचियों/सरणी पर) को बड़ी संख्या में किया जाना चाहिए।स्कैला सूची या सरणी से यादृच्छिक रूप से नमूना कैसे करें?

मुझे स्पार्क आरडीडी के लिए पता है हम इसे करने के लिए takeSample() का उपयोग कर सकते हैं, क्या स्कैला सूची/सरणी के बराबर है?

बहुत बहुत धन्यवाद।

+0

रैंडम संख्या जनरेटर स्टेटफुल हैं, तो यह मतलब नहीं है सूचियाँ इस तरह के संबंध के लिए के लिए एक समारोह। आपको स्वयं को एक लागू करना होगा (यह भी, यह एक रैखिक समय ऑपरेशन होगा)। सरणी के लिए, आप "यादृच्छिक" ऑब्जेक्ट्स से एक यादृच्छिक पूर्णांक प्राप्त कर सकते हैं जैसे: 'Random.nextInt (myArray.length)' और अनुक्रमणिका सरणी में। – Felix

+0

अहह, एनवीएम। मैंने आपकी मदद के लिए बहुत जल्दी xD – Felix

+0

धन्यवाद फ़ेलिक्स पढ़ा। – Carter

उत्तर

3

सरणियों के लिए:

import scala.util.Random 
import scala.reflect.ClassTag 

def takeSample[T:ClassTag](a:Array[T],n:Int,seed:Long) = { 
    val rnd = new Random(seed) 
    Array.fill(n)(a(rnd.nextInt(a.size))) 
} 

एक यादृच्छिक संख्या जनरेटर (rnd) अपने बीज के आधार पर करें। फिर, अपने सरणी के आकार तक 0 से यादृच्छिक संख्या के साथ एक सरणी भरें।

अंतिम चरण आपके इनपुट सरणी के इंडेक्सिंग ऑपरेटर को प्रत्येक यादृच्छिक मान लागू कर रहा है। आरईपीएल में इसका इस्तेमाल करते हुए इस प्रकार दे सकता है:

scala> val myArray = Array(1,3,5,7,8,9,10) 
myArray: Array[Int] = Array(1, 3, 5, 7, 8, 9, 10) 

scala> takeSample(myArray,20,System.currentTimeMillis) 
res0: scala.collection.mutable.ArraySeq[Int] = ArraySeq(7, 8, 7, 3, 8, 3, 9, 1, 7, 10, 7, 10, 
1, 1, 3, 1, 7, 1, 3, 7) 

सूचियों के लिए, मैं बस सूची सरणी में बदलने का और एक ही समारोह का प्रयोग करेंगे। मुझे संदेह है कि आप सूचियों के लिए वैसे भी अधिक कुशल हो सकते हैं।

यह ध्यान रखें, कि एक ही समारोह सूचियों का उपयोग कर हे ले जाएगा (एन^2) समय, सूची परिवर्तित जबकि पहले सरणियों को हे ले जाएगा (एन) समय

+1

आपकी 'टेक नमूना' विधि अनावश्यक रूप से इंडेक्स युक्त सरणी बना रही है और उसके बाद मैपिंग कर रही है। आपको शायद 'Array.fill (n) (a (rng.nextInt (a.size)) जैसे कुछ करना चाहिए) ' –

+0

हाँ, हालांकि संकलित नहीं होता है। यह आवश्यक मैनिफेस्ट खोजने में असमर्थ है। शायद आप केवल स्पष्ट पैरामीटर जोड़ सकते हैं और यह काम करेगा। – Felix

+0

मैंने इसे आपके विचार के रूप में काम करने के लिए अपडेट किया :) – Felix

23

महत्वपूर्ण है पर आसानी से -understand संस्करण इस प्रकार दिखाई देगा:

import scala.util.Random 

Random.shuffle(list).take(n) 
Random.shuffle(array.toList).take(n) 

// Seeded version 
val r = new Random(seed) 
r.shuffle(...) 
+2

"नमूना आकार सूची या सरणी की लंबाई से अधिक लंबा हो सकता है," – Felix

+0

आपने कोड को आजमाने से पहले टिप्पणी की, है ना? –

+0

मुझे पता है कि काम कैसे करते हैं, लेकिन क्या आपको नहीं लगता कि उसका मतलब है कि उसे उस मामले में अनुक्रम से बड़ा नमूना भी देना चाहिए? – Felix

1

एक दिया सरणी xs इस प्रकार के लिए, समझ के लिए एक का उपयोग करना,

for (i <- 1 to sampleSize; r = (Math.random * xs.size).toInt) yield a(r) 

नोट करें कि यादृच्छिक जनरेटर यहां यूनिट अंतराल के भीतर मान उत्पन्न करता है, जो सरणी के आकार के ऊपर रेंज करने के लिए स्केल किए जाते हैं, और सरणी पर अनुक्रमण के लिए Int में परिवर्तित हो जाते हैं।

नोट शुद्ध कार्यात्मक यादृच्छिक जनरेटर के लिए Functional Programming in Scala से उदाहरण के लिए विचार करना राज्य इकाई दृष्टिकोण, here पर चर्चा की।

नोट भी NICTA, एक और शुद्ध कार्यात्मक यादृच्छिक मान जनरेटर पर विचार करें, यह उदाहरण here के लिए सचित्र उपयोग कर रहा है।

+0

गणित नहीं है।यादृच्छिक बुरा अभ्यास? यह काफी सचमुच स्थैतिक वैश्विक राज्य है। मेरे दिमाग में – Felix

+0

स्थानीय और वैश्विक राज्य के बीच एक बड़ा अंतर है। एक बुरा है, दूसरा भयानक है। – Felix

1

शास्त्रीय रिकर्सन का उपयोग करना।

import scala.util.Random 

def takeSample[T](a: List[T], n: Int): List[T] = { 
    n match { 
     case n: Int if n <= 0 => List.empty[T] 
     case n: Int => a(Random.nextInt(a.size)) :: takeSample(a, n - 1) 
    } 
} 
+0

'टेक नमूना (सूची (1,2,3), 10000)' इसे आज़माएं, यह उड़ाएगा क्योंकि यह पूंछ-पुनरावर्ती नहीं है। – Felix

0
package your.pkg 

import your.pkg.SeqHelpers.SampleOps 

import scala.collection.generic.CanBuildFrom 
import scala.collection.mutable 
import scala.language.{higherKinds, implicitConversions} 
import scala.util.Random 

trait SeqHelpers { 

    implicit def withSampleOps[E, CC[_] <: Seq[_]](cc: CC[E]): SampleOps[E, CC] = SampleOps(cc) 
} 

object SeqHelpers extends SeqHelpers { 

    case class SampleOps[E, CC[_] <: Seq[_]](cc: CC[_]) { 

    private def recurse(n: Int, builder: mutable.Builder[E, CC[E]]): CC[E] = n match { 
     case 0 => builder.result 
     case _ => 
     val element = cc(Random.nextInt(cc.size)).asInstanceOf[E] 
     recurse(n - 1, builder += element) 
    } 

    def sample(n: Int)(implicit cbf: CanBuildFrom[CC[_], E, CC[E]]): CC[E] = { 
     require(n >= 0, "Cannot take less than 0 samples") 
     recurse(n, cbf.apply) 
    } 
    } 
} 

कोई एक:

  • Mixin SeqHelpers, उदाहरण के लिए, एक Scalatest कल्पना के साथ
  • import your.pkg.SeqHelpers._

तो शामिल करें निम्नलिखित काम करना चाहिए:

Seq(1 to 100: _*) sample 10 foreach { println } 

कलाकारों को कास्ट हटाने के लिए संपादन का स्वागत है।

अगर संचयक के संग्रह के खाली उदाहरण को बनाने का कोई तरीका है, तो समय से पहले ठोस प्रकार को जानने के बिना, कृपया टिप्पणी करें। उस ने कहा, निर्माता शायद अधिक कुशल है।

0

आप प्रतिस्थापन के बिना नमूने के लिए चाहते हैं - तरह O(n*log(n) randoms साथ ज़िप,,, randoms त्यागने ले

import scala.util.Random 
val l = Seq("a", "b", "c", "d", "e") 
val ran = l.map(x => (Random.nextFloat(), x)) 
    .sortBy(_._1) 
    .map(_._2) 
    .take(3) 
संबंधित मुद्दे