2012-08-12 10 views
11

आर में, श्रेणी से पूर्णांक निकालने का एक प्रभावी तरीका क्या है?श्रेणियों से पूर्णांक निकालें

मान लीजिए कि मैं पर्वतमाला के एक मैट्रिक्स (स्तम्भ 1 = शुरू, कॉलम 2 = अंत)

1 5 
3 6 
10 13 

मैंने किसी चीज़ में मैट्रिक्स में सभी श्रेणियों के शामिल अद्वितीय पूर्णांकों स्टोर करने के लिए करना चाहते हैं करते हैं:

1 
2 
3 
4 
5 
6 
10 
11 
12 
13 

यह ~ 4 मिलियन रेंज वाले मैट्रिक्स पर लागू होगा, इसलिए उम्मीद है कि कोई ऐसा समाधान प्रदान कर सकता है जो कुछ हद तक कुशल है।

उत्तर

5

मैं नहीं जानता कि यह विशेष रूप से प्रभावी है, लेकिन अगर पर्वतमाला के अपने मैट्रिक्स ranges तो है निम्नलिखित काम करना चाहिए:

unique(unlist(apply(ranges, 1, function(x) x[1]:x[2]))) 
5

उपयोग sequence और rep:

x <- matrix(c(1, 5, 3, 6, 10, 13), ncol=2, byrow=TRUE) 

ranges <- function(x){ 
    len <- x[, 2] - x[, 1] + 1 
    #allocate space 
    a <- b <- vector("numeric", sum(len)) 
    a <- rep(x[, 1], len) 
    b <- sequence(len)-1 
    unique(a+b) 
} 

ranges(x) 
[1] 1 2 3 4 5 6 10 11 12 13 

चूंकि यह केवल वेक्टरिज्ड कोड का उपयोग करता है, यह बड़े डेटा सेट के लिए भी तेज़ होना चाहिए।

set.seed(1) 
xx <- sample(1e6, 1e6) 
xx <- matrix(c(xx, xx+sample(1:100, 1e6, replace=TRUE)), ncol=2) 
str(xx) 
int [1:1000000, 1:2] 265509 372124 572853 908206 201682 898386 944670 660794 629110 61786 ... 

system.time(zz <- ranges(xx)) 
user system elapsed 
    4.33 0.78 5.22 

str(zz) 
num [1:51470518] 265509 265510 265511 265512 265513 ... 
+0

मुझे लगता है कि ओपी चाहता है कि नतीजा केवल एक बार पूर्णांक को प्रदर्शित करे। – seancarmody

+0

मैंने समय की तुलना की है: मेरा जवाब निश्चित रूप से चलाने के लिए धीमा है! – seancarmody

+0

@seancarmody ** अद्वितीय ** पूर्णांक के लिए आवश्यकता को हाइलाइट करने के लिए धन्यवाद। मैं अपना जवाब संपादित करूंगा। – Andrie

12

मान लीजिए आप एक नंबर लाइन पर था शुरू = 3, अंत = 7, और आप एक '1' के रूप में प्रत्येक चिह्नित था: मेरी मशीन पर 1 लाख पंक्तियों की एक इनपुट मैट्रिक्स को चलाने के लिए ~ 5 सेकंड लेता है 1

starts:  0 0 1 0 0 0 0 0 0 ... 
ends + 1: 0 0 0 0 0 0 0 1 0 ... 

शुरू होता है शून्य से समाप्त होता है के संचयी योग, और दोनों के बीच अंतर के संचयी योग पर शुरू,

cumsum(starts): 0 0 1 1 1 1 1 1 1 ... 
cumsum(ends + 1): 0 0 0 0 0 0 0 1 1 ... 
diff:    0 0 1 1 1 1 1 0 0 

है और diff में 1 के स्थानों

हैं
which(diff > 0): 3 4 5 6 7 

उपयोग सारणीबद्ध कई शुरू होता है के लिए अनुमति देने के लिए/एक ही स्थान पर समाप्त होता है, और

range2 <- function(ranges) 
{ 
    max <- max(ranges) 
    starts <- tabulate(ranges[,1], max) 
    ends <- tabulate(ranges[,2] + 1L, max) 
    which(cumsum(starts) - cumsum(ends) > 0L) 
} 

प्रश्न के लिए, यह देता है

> eg <- matrix(c(1, 3, 10, 5, 6, 13), 3) 
> range2(eg) 
[1] 1 2 3 4 5 6 10 11 12 13 

यह Andrie के उदाहरण

के लिए, बहुत तेजी से है
> system.time(runs <- range2(xx)) 
    user system elapsed 
    0.108 0.000 0.111 

(यह डीएनए सेक की तरह थोड़ा लगता है एनसी विश्लेषण, जिसके लिए GenomicRanges आपका मित्र हो सकता है; आप पढ़ने पर coverage और slice फ़ंक्शंस का उपयोग करेंगे, शायद readGappedAlignments के साथ इनपुट करें)।

+0

यह दो अन्य समाधानों की तुलना में काफी तेज है। प्रभावशाली। – seancarmody

+0

+1 शानदार ... – Andrie

3

यह कुछ नहीं के रूप में सरल है:

x <- matrix(c(1, 5, 3, 6, 10, 13), ncol=2, byrow=TRUE) 
do.call(":",as.list(range(x))) 
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 

संपादित

ऐसा लगता है कि मैं छड़ी के गलत छोर है, लेकिन मेरा उत्तर, union उपयोग करने के लिए संशोधित किया जा सकता है, हालांकि यह है unique के लिए सिर्फ एक रैपर:

Reduce("union",apply(x,1,function(y) do.call(":",as.list(y)))) 
[1] 1 2 3 4 5 6 10 11 12 13 
+0

ध्यान दें कि ओपी में, 7, 8 और 9 वांछित परिणाम में प्रकट नहीं होते हैं। विचार यह है कि प्रत्येक श्रेणी के संघ को पूरी मैट्रिक्स में सबसे कम से उच्चतम तक पूर्ण सीमा तक वापस नहीं करना है। – seancarmody

+0

@seancarmody आह, मैं देखता हूं, मुझे गलत समझा जाता है, तो आपका जवाब सही था जो मैं सोच रहा था। मैं इस – James

+1

को वास्तव में हटा दूंगा, मुझे इसे संशोधित करने का एक तरीका मिला। काफी अलग नहीं है, लेकिन पूर्णता के लिए एक और विकल्प है – James

संबंधित मुद्दे