2015-04-22 13 views
7

Mam dwa wektoryKombajny każdy element wektora z innym wektorem w R

x <- c(2, 3, 4) 
y <- rep(0, 5) 

Chcę uzyskać następujące dane wyjściowe:

> z 
2, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0 

Jak mogę utworzyć z? Próbowałem użyć paste i c, ale nic nie działa. Jedyne, co mogę wymyślić, to używanie for() i jest strasznie powolny. Mam googleed to i jestem pewien, że rozwiązanie jest tam i po prostu nie trafiam odpowiednich słów kluczowych.

UPDATE: Dla celów analizy porównawcze:

Stosując rozwiązanie Nicoli:

> system.time(
+ precipitation <- `[<-`(numeric(length(x)*(length(y)+1)),seq(1,by=length(y)+1,length.out=length(x)),x) 
+) 
user system elapsed 
0.419 0.407 0.827 

Jest śmiesznie szybko! Muszę powiedzieć! Czy ktoś może mi to wyjaśnić? Moja for(), o której wiem, że zawsze jest błędna w R, zajęłaby co najmniej jeden dzień, nawet jeśli się skończyła.

Inne propozycje:

> length(prate) 
[1] 4914594 
> length(empty) 
[1] 207 
> system.time(
+ precipitation <- unlist(sapply(prate, FUN = function(prate) c(prate,empty), simplify=FALSE)) 
+) 
user system elapsed 
16.470 3.859 28.904 

musiałem zabić

len <- length(prate) 
precip2 <- c(rbind(prate, matrix(rep(empty, len), ncol = len))) 

Po 15 minutach.

+0

Choć nie tak szybko, jak @ Nicoli Inną opcją jest 'rep (x, każdy = długość (y) +1) * c (1, y)' – akrun

+0

Zrobiłem edycję, aby przyspieszyć rzeczy, gdy 'y' składa się z zer. – nicola

Odpowiedz

4

można spróbować to

unlist(sapply(x, FUN = function(x) c(x,y), simplify=FALSE)) 
[1] 2 0 0 0 0 0 3 0 0 0 0 0 4 0 0 0 0 0 

lub prostsze od @docendodiscimus

unlist(lapply(x, FUN = function(x) c(x,y))) 
+1

Możesz użyć 'lapply', więc nie musisz określać uproszczenia = FALSE –

+0

Nie próbowałem innych sugestii, ale jest to bardzo szybkie (zajmuje odpowiednio 30 sekund w stosunku do mojej pętli, która zajęłaby co najmniej jeden dzień) . –

+0

@cddesjardins byłoby interesujące, gdybyś przetestował również inne odpowiedzi na szybkość. –

2

Można także spróbować wektorować następująco

len <- length(x) 
c(rbind(x, matrix(rep(y, len), ncol = len))) 
## [1] 2 0 0 0 0 0 3 0 0 0 0 0 4 0 0 0 0 0 

Bardziej kompaktowy, lecz potencjalnie wolniejszy opcji (przesłane przez @akrun) będzie

c(rbind(x, replicate(len, y))) 
## [1] 2 0 0 0 0 0 3 0 0 0 0 0 4 0 0 0 0 0 
+0

Wypróbowałem niektóre testy porównawcze dla wektora 1e6 'x' i'y 'dla długości 100. Użycie 'dim <-' jest nieco szybsze, rozwiązanie @Mamoun Benghezal pojawiło się jako pierwsze, rozwiązanie' replicate' jest najwolniejsze, choć w skali 1 vs 2,9 – akrun

+0

@krun. Ciekawe. Dziwne, ale –

1

Można spróbować:

c(sapply(x, 'c', y)) 
#[1] 2 0 0 0 0 0 3 0 0 0 0 0 4 0 0 0 0 

lub szalone rozwiązanie GUSB i pasty ..

library(functional) 
p = Curry(paste0, collapse='') 

as.numeric(strsplit(p(gsub('(.*)$', paste0('\\1',p(y)),x)),'')[[1]]) 
#[1] 2 0 0 0 0 0 3 0 0 0 0 0 4 0 0 0 0 0 
5

Wydaje szybciej z jakiegoś powodu:

unlist(t(matrix(c(as.list(x),rep(list(y),length(x))),ncol=2))) 

Powyższe rozwiązanie jest ogólny, w tym sensie, że zarówno x i y c mieć jakąkolwiek wartość. W przypadku PO, gdzie y wykonana jest tylko 0, to szybko jak to tylko możliwe:

`[<-`(numeric(length(x)*(length(y)+1)),seq(1,by=length(y)+1,length.out=length(x)),x) 
#[1] 2 0 0 0 0 0 3 0 0 0 0 0 4 0 0 0 0 0 

Edit

Zdaję sobie sprawę, byłem bardzo tajemnicze i kod I nie jest produkowany łatwe do naśladowania, mimo że jest tylko jedną linią.Wyjaśnię szczegółowo, co robi drugie rozwiązanie.

Przede wszystkim zauważysz, że wynikowy wektor będzie miał wartości zawarte w x oraz zerach w y powtórzonych length(x) razy. Łącznie będzie to długi czas: length(x) + length(x)*length(y) lub length(x)*(length(y)+1). Więc tworzymy wektor z zer tylko tak długo, jak potrzeba:

res<-numeric(length(x)*(length(y)+1)) 

Teraz musimy umieścić wartości x w res. Zauważamy, że pierwsza wartość x zajmuje pierwszą wartość w res; drugi będzie po length(y)+1 od pierwszego i tak dalej, aż wszystkie wartości length(x) zostaną wypełnione. Możemy stworzyć wektor indeksów w których umieszcza wartości x:

indices<-seq.int(1,by=length(y)+1,length.out=length(x)) 

A potem dokonać Zamiennik:

res[indices]<-x 

Mój wiersz był tylko skrót do trzech linii powyżej. Mam nadzieję, że to trochę wyjaśnia.

+1

Twoje rozwiązanie jest jak dotąd najszybsze. Myślałem, że 't' może zmniejszyć prędkość, ale nie było tak, – akrun

+1

Tak, ciekawe rozwiązanie. –

+1

Bardzo ładne rozwiązanie. Możesz użyć 'integer' zamiast' numeric', aby było jeszcze szybciej. – cryo111

1

Oto kolejny sposób:

options(scipen=100) 
as.numeric(unlist(strsplit(as.character(x * 10^5), ""))) 

A niektóre benchmarki:

microbenchmark({as.numeric(unlist(strsplit(as.character(x*10^5), "")))}, {unlist(t(matrix(c(as.list(x),rep(list(y),length(x))),ncol=2)))}, {unlist(sapply(x, FUN = function(x) c(x,y), simplify=FALSE))}, times=100000) 
Unit: microseconds 
                     expr 
      {  as.numeric(unlist(strsplit(as.character(x * 10^5), ""))) } 
{  unlist(t(matrix(c(as.list(x), rep(list(y), length(x))), ncol = 2))) } 
     {  unlist(sapply(x, FUN = function(x) c(x, y), simplify = FALSE)) } 
    min  lq  mean median  uq  max neval 
9.286 10.644 12.15242 11.678 12.286 1650.133 100000 
9.485 11.164 13.25424 12.288 13.067 1887.761 100000 
5.607 7.429 9.21015 8.147 8.784 30457.994 100000 

A oto kolejny pomysł (ale wydaje się powolny):

r = rle(1) 
r$lengths = rep(c(1,5), length(x)) 
r$values = as.vector(rbind(x, 0)) 
inverse.rle(r) 
+0

Na podstawie 'x' z wpisu OP, otrzymuję' as.numeric (unlist (strsplit (as.character (x * 10^5), ""))) # [1] 2 NA NA 0 5 3 NA NA 0 5 4 NA NA 0 5' co nie jest oczekiwanym rezultatem – akrun

+0

Zabawne, mam rację: 'as.numeric (unlist (strsplit (as.znak (x * 10^5), ""))) [1] 2 0 0 0 0 0 3 0 0 0 0 0 4 0 0 0 0 0' – nsheff

+0

@akrun oh tak - wyłącz notację naukową: ' options (scipen = 100) ' – nsheff

Powiązane problemy