根据向量移动行值

时间:2018-08-15 13:41:49

标签: r datatable

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")

我想根据此向量的值向右或向左移动行的非零值:

vect <- c(-2, 1, 0, 2, 2, 2, 2, 2, -2)

第一行将向左移动两列以获得:

344 34 93 76 190 78 0 0 0

第二行将向右移动一列以获得:

0 0 0 350 16 45 22 21 0 

在我以前的文章中,有人建议使用dplyr包的mutate函数,该函数效果很好,但需要一个整数

1 个答案:

答案 0 :(得分:1)

这是一个tidyverse解决方案,其中使用map2将平移值应用于数据集的相应行:

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

关键是如果移位值为正,则使用lag,否则使用lead和绝对值。