Reputation: 474
data.tab <- read.table(text = "
0 0 344 34 93 76 190 78 0
0 0 350 16 45 22 21 0 0
0 0 366 11 87 65 71 0 0
0 0 780 28 46 33 30 0 0
0 0 997 55 98 65 12 0 0
0 0 402 30 11 18 198 0 0")
I want to shift non zero value of rows to the right or to the left according to values this vector :
vect <- c(-2, 1, 0, 2, 2, 2, 2, 2, -2)
.
The first row will be shifted by two columns to the left to obtain :
344 34 93 76 190 78 0 0 0
The second row will be shifted by one column to the right to obtain:
0 0 0 350 16 45 22 21 0
In my previous post some one suggested the mutate function of dplyr package which works well, but required a single integer
Upvotes: 0
Views: 397
Reputation: 16121
Here is a tidyverse
solution using map2
to apply a shift value to the corresponding row of your dataset:
data.tab <- read.table(text = "
0 0 344 34 93 76 190 78 0
0 0 350 16 45 22 21 0 0
0 0 366 11 87 65 71 0 0
0 0 780 28 46 33 30 0 0
0 0 997 55 98 65 12 0 0
0 0 402 30 11 18 198 0 0")
library(tidyverse)
# for reproducibility
set.seed(15)
data.tab %>%
group_by(id = row_number()) %>% # group by row id
nest() %>% # nest data
mutate(shift = sample(-2:2, nrow(data.tab), replace=TRUE), # create and add the shift values for each row
d = map2(shift, data, ~if(.x >= 0) lag(.y, .x, default = 0L) else lead(.y, abs(.x), default = 0L))) %>% # apply shift value to corresponding rows
unnest(d) %>% # unnest shifted data
select(-id, -data) # remove unnecessary columns
# # A tibble: 6 x 10
# shift V1 V2 V3 V4 V5 V6 V7 V8 V9
# <int> <int> <int> <int> <int> <int> <int> <int> <int> <int>
# 1 1 0 0 0 344 34 93 76 190 78
# 2 -2 350 16 45 22 21 0 0 0 0
# 3 2 0 0 0 0 366 11 87 65 71
# 4 1 0 0 0 780 28 46 33 30 0
# 5 -1 0 997 55 98 65 12 0 0 0
# 6 2 0 0 0 0 402 30 11 18 198
The key point it to use lag
if the shift value is positive, otherwise use lead
and the absolute shit value.
Upvotes: 2