2017-08-30 5 views
8

में n शून्य से अलग कर दिया मैं एक वेक्टर xस्प्लिट वेक्टर अलग समूह

x = c(1, 1, 2.00005, 1, 1, 0, 0, 0, 0, 1, 2, 0, 3, 4, 0, 0, 0, 0, 1, 2, 3, 1, 3) 

मैं n द्वारा अलग किए गए मान विभाजित करने की आवश्यकता को विभिन्न समूहों में या एक से अधिक शून्य (इस मामले में, n3 है मान लेते हैं) है।

वांछित उत्पादन होगा

list(x1 = c(1, 1, 2.00005, 1, 1), 
    x2 = c(1, 2, 0, 3, 4), 
    x3 = c(1, 2, 3, 1, 3)) 
#$x1 
#[1] 1.00000 1.00000 2.00005 1.00000 1.00000 

#$x2 
#[1] 1 2 0 3 4 

#$x3 
#[1] 1 2 3 1 3 

निम्नलिखित काम नहीं करता है, क्योंकि यह x विभाजन जब भी वहाँ एक समूह में कम से कम n शून्य कर रहे हैं।

temp = cumsum(x == 0) 
split(x[x!=0], temp[x!=0]) 
#$`0` 
#[1] 1.00000 1.00000 2.00005 1.00000 1.00000 

#$`4` 
#[1] 1 2 

#$`5` 
#[1] 3 4 

#$`9` 
#[1] 1 2 3 1 3 
+2

'lapply (strsplit (strsplit (gsub ('(, 0) {3,},', ',', पेस्ट (एक्स, पतन = ',')), ';') [[1L ]], ','), as.numeric) ' – rawr

उत्तर

6

यहां मेरा प्रयास है। यह विधि शून्य के रन को प्रतिस्थापित करती है जो एनए के साथ 3 से कम या बराबर होती है। चूंकि split() का उपयोग करते समय एनए हटा दिया जाता है, इसलिए हमें वांछित आउटपुट के साथ छोड़ दिया जाता है।

x <- c(1, 1, 2.00005, 1, 1, 0, 0, 0, 0, 1, 2, 0, 3, 4, 0, 0, 0, 0, 1, 2, 3, 1, 3) 

ll <- with(rle(x == 0), { 
    ifelse(x == 0 & (seq_along(x) != cumsum(lengths)[lengths <= 3 & values]), NA, x) 
}) 

split(x, with(rle(is.na(ll)), rep(1:length(lengths), lengths) + ll * 0)) 
# $`1` 
# [1] 1.00000 1.00000 2.00005 1.00000 1.00000 
# 
# $`3` 
# [1] 1 2 0 3 4 
# 
# $`5` 
# [1] 1 2 3 1 3 
+0

यह कोड थोड़ा अलग इनपुट के साथ काम नहीं कर रहा है: x <- c (1, 1, 2.00005, 1, 1, 0, 0, 0, 0 , 1, 2, 0, 3, 4, 0, 0, 0, 0, 1, 2, 3, 0, 0, 1, 3) – e3bo

4

यहाँ rle, split के साथ एक तरीका है, और इस प्रकार lapply

# get RLE 
temp <- rle(x) 
# replace values with grouping variables 
temp$values <- cumsum(temp$values == 0 & temp$lengths > 2) 

# split on group and lapply through, dropping 0s at beginning which are start of each group 
lapply(split(x, inverse.rle(temp)), function(y) y[cummax(y) > 0]) 
$`0` 
[1] 1.00000 1.00000 2.00005 1.00000 1.00000 

$`1` 
[1] 1 2 0 3 4 

$`2` 
[1] 1 2 3 1 3 

lapply के बिना एक दूसरी विधि है के रूप में

# get RLE 
temp <- rle(x) 
# get positions of 0s that force grouping 
changes <- which(temp$values == 0 & temp$lengths > 2) 
# get group indicators 
temp$values <- cumsum(temp$values == 0 & temp$lengths > 2) 
# make 0s a new group 
temp$values[changes] <- max(temp$values) + 1L 

# create list 
split(x, inverse.rle(temp)) 
$`0` 
[1] 1.00000 1.00000 2.00005 1.00000 1.00000 

$`1` 
[1] 1 2 0 3 4 

$`2` 
[1] 1 2 3 1 3 

$`3` 
[1] 0 0 0 0 0 0 0 0 

अंत में, आप बस छोड़ चाहते हैं अंतिम सूची आइटम, जैसे head(split(x, inverse.rle(temp)), -1)

2

यहाँ rle और inverse.rle कई बार का उपयोग कर एक्स (x_sub) और समूह संख्या (group_sub) के एक सबसेट बनाने के लिए एक विचार है। अंत में, अंतिम परिणाम प्राप्त करने के लिए split का उपयोग करें।

x <- c(1, 1, 2.00005, 1, 1, 0, 0, 0, 0, 1, 2, 0, 3, 4, 0, 0, 0, 0, 1, 2, 3, 1, 3) 

### Step 1: Filtet the index with values == 0 and length > 3 
x2 <- as.integer(x != 0) 
run <- rle(x2) 
index <- which(run$values == 0 & run$lengths > 3) 

### Step 2: Replace the values in index to -1 
### Create an intermediate index (x3) 
run2 <- run 
run2$values[index] <- -1 
run2$values[run2$values == 0] <- 1 
x3 <- inverse.rle(run2) 

### Step 3: Create grouping variable (x4) 
run3 <- rle(x3) 
run3$values <- 1:length(run3$values) 
x4 <- inverse.rle(run3) 

### Step 4: Subset x by x3 and x4 (x_sub) and create group number (group_sub) 
x_sub <- x[x3 != -1] 
group_sub <- x4[x3 != -1] %/% 2 + 1 

### Step 5: Split x_sub to get the final output (final_list) 
final_list <- split(x_sub, f = group_sub) 

final_list 
$`1` 
[1] 1.00000 1.00000 2.00005 1.00000 1.00000 

$`2` 
[1] 1 2 0 3 4 

$`3` 
[1] 1 2 3 1 3 
3

इस विधि बस थोड़ा सा क्या आप पहले से ही प्रस्तावित से अलग है, और उदाहरण के अधिकतम + 1 के लिए एक मूल्य के द्वारा n या अधिक शून्य के सभी हिस्सों की जगह का एक पहला कदम एक्स में नहीं मिला, में शामिल हैं:

r = rle(x) 
val = max(x,na.rm=T)+1 
r$values[r$values==0 & r$lengths>2] = val 
x2 = inverse.rle(r) 
temp = cumsum(x2 == val) 
split(x2[x2!=val], temp[x2!=val]) 

$`0` 
[1] 1.00000 1.00000 2.00005 1.00000 1.00000 

$`4` 
[1] 1 2 0 3 4 

$`8` 
[1] 1 2 3 1 3 
2

फिर भी rle (दो बार) और inverse.rle का उपयोग करके एक और समाधान।

n <- 3 
r <- rle(as.integer(x == 0)) 
r$values[r$values == 1 & r$lengths < n] <- 0 
r <- rle(inverse.rle(r)) 

group <- integer(length(x)) 
start <- 1 
for(i in seq_along(r$values)){ 
    group[start:(start + r$lengths[i] - 1)] <- c(1L, rep(0L, r$lengths[i] - 1)) 
    start <- start + r$lengths[i] 
} 

इसी समय मुझे एहसास हुआ कि कोड जो ऊपर लूप तैयार करता है और लूप स्वयं को बहुत सरल बना सकता है। इसे पूरा करने के लिए, मैं कोड की आरंभिक पंक्तियों को दोहरा दूंगा।

r <- rle(as.integer(x == 0)) 
r$values[r$values == 1 & r$lengths < n] <- 0 

# This is the simplification 
group <- c(1L, diff(inverse.rle(r)) != 0) 

res <- split(x, cumsum(group)) 
res <- res[-which(sapply(res, function(y) all(y == 0)))] 
res 
#$`1` 
#[1] 1.00000 1.00000 2.00005 1.00000 1.00000 
# 
#$`3` 
#[1] 1 2 0 3 4 
# 
#$`5` 
#[1] 1 2 3 1 3 
संबंधित मुद्दे