0

Given are two vectors:

vec_nums <- 1:20
vec_ltrs <- letters[1:10]

I would like to write a function that would merge them some each element from the second vectors appears on the precisely defined position within the first vector. For example, running:

vec_mrg <- funMergeVectsByPlace(x = vec_num, y = vec_ltrs, position = 3)

Should return vec_mrg of the following content:

 [1] "a"  "b" "1"  "c"  "d"  "2"  "f"  "g"  "3"  "i"  "j"  "4"  "l"  "m"  "5" ...

Desired characteristics:

  1. The function places element from the vector passed via the y = on the position given in the position = counting from the left hand side. So position = 3 should be understood as *every third place" accounting for 3, 6, ...
  2. The function should work on numeric string and factor vectors and return an ordered factor.
  3. The function should work on factor, string and numeric vectors
  4. In case of vector y being shorter than than the number of inserts in the x the function should return remaining part of x without any additions

Suggested structure

I would envisage for the function to be of this structure:

funMergeVectsByPlace <- function(x,y position = 3) {

  # Convert
  vec_a <- as.character(x)
  vec_b <- as.character(y)


  # Missing part
  # Combine two vectors 


  # Create ordered factor
  vec_fac <- factor(vec_mrg, 
                   # levels = 
                   # I want the levels to reflect the order of elements in the vec_merg
                   )

  # Return
  return(vec_fac)
}

Samples

Simplest

Concerning attempts, simplest approach:

vec_mrg <- c(vec_nums, vec_ltrs)
vec_mrg <- order(vec_mrg)

But this would not create the order

Loop

for (i in 1:length(vec_nums)) {
  pos <- position 
  vec_nums[pos] <- vec_ltrs[i]
  pos <- pos + pos
  # i will be out of bounds and the way to move the other vector is missing
}
Konrad
  • 17,740
  • 16
  • 106
  • 167
  • Anything you've already tried yourself? Where does messy_vec and the regex part come from? – Heroka Nov 06 '15 at 10:47
  • [CodeGolf](http://codegolf.stackexchange.com/) assignment? –  Nov 06 '15 at 10:48
  • @Pascal could be but I just want to get to work at this stage. – Konrad Nov 06 '15 at 10:53
  • @Heroka from another discussion on ordering messy strings. I can actually change it as it's not that relevant to the task at hand. – Konrad Nov 06 '15 at 10:54
  • @Konrad do you realize SO is not a code-writing service? I think many people here love a puzzle but some effort/ideas of your own in how to solve it instead of "do this" might not go amiss. – Heroka Nov 06 '15 at 11:00
  • @Heroka I do realise that. Personally, I find the question amusing and conceptually not much different from similar broad questions that received recognition across the SO community ([1](http://stackoverflow.com/questions/3402371/combine-two-data-frames-by-rows-rbind-when-they-have-different-sets-of-columns), [2](http://stackoverflow.com/questions/26138008/combine-vectors-into-one-number). Obviously, if there is no sufficient interest, I will delete the post. – Konrad Nov 06 '15 at 11:05
  • @Heroka & Konrad: This question is not that bad, because the answers show how bad growing structures in `for`-loops are. – mra68 Nov 06 '15 at 12:55

2 Answers2

1
vec_mrg <- function(x,y,pos) {
  res <- y
  counter <- seq(floor(length(y)/(pos-1)))
  for(i in counter) {
    res <- append(res, x[i], seq(pos-1,by=pos, length.out=length(counter))[i])
  }
  res
}

vec_mrg(vec_nums, vec_ltrs, 3)
#[1] "a" "b" "1" "c" "d" "2" "e" "f" "3" "g" "h" "4" "i" "j"
#[15] "5"
Pierre L
  • 28,203
  • 6
  • 47
  • 69
1

A loop-free solution:

funMergeVectsByPlace <- function( x, y, position )
{
  n <- min( length(y)%/%(position-1), length(x) )    
  A <- rbind( matrix(head(y,n*(position-1)),position-1), head(x,n) )

  rest <- c( x[-(1:n)], y[-(1:(n*(position-1)))] )

  c(c(A),rest)
}

Speed comparison with Lafortunes solution:

> library(microbenchmark)

> vec_nums <- 1:20

> vec_ltrs <- letters[1:10]

> microbenchmark(Lafortune  = vec_mrg(vec_nums,vec_ltrs,3),
+                mra68 = funMergeVectsByPlace(vec_nums,vec_ltrs,3),
+                times .... [TRUNCATED] 
Unit: microseconds
      expr     min      lq      mean  median      uq      max neval
 Lafortune 137.677 143.112 161.12006 146.734 153.980 2931.512 10000
     mra68  77.443  81.067  92.13208  83.331  86.954 2718.204 10000

Larger vectors:

> vec_nums <- 1:2000

> vec_ltrs <- letters[rep(1:10,100)]

> microbenchmark(Lafortune  = vec_mrg(vec_nums,vec_ltrs,3),
+                mra68 = funMergeVectsByPlace(vec_nums,vec_ltrs,3),
+                times .... [TRUNCATED] 
Unit: milliseconds
      expr       min        lq      mean    median        uq      max neval
 Lafortune 32.993883 40.991796 63.758011 51.171020 90.122351 456.9748  1000
     mra68  1.101865  1.489533  2.468496  1.751299  3.338881 230.0460  1000

> v1 <- vec_mrg(vec_nums,vec_ltrs,3)

> v2 <- funMergeVectsByPlace(vec_nums,vec_ltrs,3)
> 

Notice that the vec_mrg function does not append the rest of the x vector to the result, but funMergeVectsByPlace does. Otherwise the results are the same:

> v1 <- vec_mrg(1:20,letters[1:10],3)

> v2 <- funMergeVectsByPlace(1:20,letters[1:10],3)

> v1
 [1] "a" "b" "1" "c" "d" "2" "e" "f" "3" "g" "h" "4" "i" "j" "5"

> v2
 [1] "a"  "b"  "1"  "c"  "d"  "2"  "e"  "f"  "3"  "g"  "h"  "4"  "i"  "j"  "5"  "6"  "7"  "8"  "9"  "10" "11" "12" "13" "14" "15" "16" "17" "18" "19" "20"

> identical(v1,v2[1:length(v1)])
[1] TRUE
> 

Neither vec_mrg nor funMergeVectsByPlace return factors. If one includes factor(...), both functions are getting slower, but funMergeVectsByPlace is still faster than vec_mrg.

mra68
  • 2,960
  • 1
  • 10
  • 17