Author: Fred Hasselman
Date: 2022-08-16

# Changing vectors and values: Replace, Add/Subtract, Trim, Pad

#### Fred Hasselman

#### 2022-08-16

## Replace values

The examples below use a variety of infix functions that can be used to change values in a vector.

### Use index finders

If you already know indices of the columns or rows you want to change, these functions will not be shorter, however often the opposite is the case, one knows a name, but not the exact column/row number. In these cases the infix functions are much shorter.

    d <- data.frame(x=1:5, y=6, txt=paste0("delta = ",6-1:5), row.names=paste0("ri",5:1), stringsAsFactors = FALSE)
    knitr::kable(d)

| x | y | txt
--- | --- | --- | ---
ri5 | 1 | 6 | delta = 5
ri4 | 2 | 6 | delta = 4
ri3 | 3 | 6 | delta = 3
ri2 | 4 | 6 | delta = 2
ri1 | 5 | 6 | delta = 1

    # Change a column name based on the current name
    # colnames(d)[colnames(d)%in%"y"] <- "Yhat"
      colnames(d)["y"%ci%d] <- "Yhat"
      1:3%ci%d
    > [1] "x"    "Yhat" "txt"

    # Use a range of values in variable to change cells
    # d$txt[d$x>=2&d$x<=4] <- "Changed!"
      d$txt[d$x%[]%c(2,4)] <- "Changed!"
      knitr::kable(d)

| x | Yhat | txt
--- | --- | --- | ---
ri5 | 1 | 6 | delta = 5
ri4 | 2 | 6 | Changed!
ri3 | 3 | 6 | Changed!
ri2 | 4 | 6 | Changed!
ri1 | 5 | 6 | delta = 1

    # Use row names to change cells
    # d$txt[rownames(d)%in%c("ri2,ri4")] <- "Changed again!"
      d$txt[c("ri2","ri4")%ri%d] <- "Changed again!"
      knitr::kable(d)

| x | Yhat | txt
--- | --- | --- | ---
ri5 | 1 | 6 | delta = 5
ri4 | 2 | 6 | Changed again!
ri3 | 3 | 6 | Changed!
ri2 | 4 | 6 | Changed again!
ri1 | 5 | 6 | delta = 1

### The rose tinted infix

Use the rose tinted glasses `%00%` to change any nasty number into a cute fluffy value of your choice.

    # Replace special numerical values
    c(0,Inf,1,NA,2,NaN,3) %00% NA
    > [1]  0 NA  1 NA  2 NA  3

    # Also works with NULL
    NULL %00% NA
    > [1] NA

    # Length 0 vectors
    logical(0) %00% NA
    > [1] NA

    numeric(0) %00% "lenghth 0!!"
    > [1] "lenghth 0!!"
             0 %00% "lenghth 0!!"
    > [1] 0

## Using counter infix functions

The counter infix functions can add or subtract values from an input source. This can be a value, or an object.

     # Signed increment
     # Notice the difference between passing an object and a value for counter

     # Value
     (11 %+-% -5)
    > [1] 6
     (11 %+-%  5)
    > [1] 16

     # Object
     i <- 11
     (i %+-% -5)
    > [1] 6
     (i %+-%  5)
    > [1] 11

     # This means we can use the infix in a while ... statement
     # WARNING: As is the case for any while ... statement, be careful not to create an infinite loop!
     i <- 5
     while(i > -5){
       i %+-% -1
       print(i)
     }
    > [1] 4
    > [1] 3
    > [1] 2
    > [1] 1
    > Warning in i %+-% -1: Positive valued counter changed sign (counter <= 0)!
    > [1] 0
    > [1] -1
    > [1] -2
    > [1] -3
    > [1] -4
    > [1] -5

     # Non-negative increment
     # Notice the difference between passing an object and a value for counter

     # Value
     (0 %++% 5)
    > [1] 5
     (0 %++% 5)
    > [1] 5

     # Object
     i <- 0
     (i %++% 5)
    > [1] 5
     (i %++% 5)
    > [1] 10

     # This means we can use the infix in a while ... statement
     # WARNING: As is the case for any while ... statement, be careful not to create an infinite loop!

     i <- 0
     while(i < 20){
     i %++% 5
     print(i)
     }
    > [1] 5
    > [1] 10
    > [1] 15
    > [1] 20

## Padding vectors

Use `x %[+% n` to add `n` `0`s to the front of `x`. Similarly, `%+]%` would add to the rear, and `%[+]%` to front and rear. If you want to add a value other than `0`, use `x %[+% c(n,v)`

    set.seed(1234)
     (x <- round(runif(10,1,10)))
    >  [1] 2 7 6 7 9 7 1 3 7 6

     # Pad front with 10 zeros
     x%[+%5
    >  [1] 0 0 0 0 0 2 7 6 7 9 7 1 3 7 6
     # Same as
     x%[+% c(5,0)
    >  [1] 0 0 0 0 0 2 7 6 7 9 7 1 3 7 6

     # Pad rear with zeros
     x%+]%5
    >  [1] 2 7 6 7 9 7 1 3 7 6 0 0 0 0 0
     # Same as
     x%+]%c(5,0)
    >  [1] 2 7 6 7 9 7 1 3 7 6 0 0 0 0 0

     # Pad front + rear with NA
     x%[+]%c(4,NA)
    >  [1] NA NA  2  7  6  7  9  7  1  3  7  6 NA NA

     # Pad front + rear of a character vector
     "yes"%[+]%c(2,"no")
    > [1] "no"  "yes" "no"
     "yes"%[+]%c(1,"no")
    > [1] "yes" "no"
     "yes"%[+]%c(0,"no")
    > [1] "yes"

## Trimming vectors

Use `x %[-% n`, `x %-]% n`, or `x %[-]% c(n,m)` to trim `x` by `n` from the front, rear, or, `n` from the front and `m` fro the rear. When `n` is uneven, `floor(n)` wil be trimmed from the front and `ceiling(n)` from the rear.

     set.seed(4321)
     (x <- round(runif(10,1,10)))
    >  [1] 4 9 5 1 8 8 8 9 5 5

     # Trim front
     x%[-%5
    > [1] 8 8 9 5 5

     # Trim rear
     x%-]%5
    > [1] 4 9 5 1 8

     # Trim front + rear
     x%[-]%c(2,4)
    > [1] 5 1 8 8

     x%[-]%3
    > [1] 9 5 1 8 8 8 9