在 R 中的数据框中移动值
Shift values in a dataframe in R
我有一个数据框:
dt <- read.table(text = "
0 344 34 0 0
0 350 16 0 0
0 366 11 0 0
0 376 8 0 0
0 380 28 0 0
0 397 55 0 0
0 398 45 0 0
0 400 19 0 0
0 402 30 0 0")
我想将 1/3 的行随机向右移动一列,例如:
dt1 <- read.table(text = "
0 344 34 0 0
0 350 16 0 0
0 0 366 11 0
0 376 8 0 0
0 0 380 28 0
0 0 397 55 0
0 398 45 0 0
0 400 19 0 0
0 402 30 0 0")
是否可以有一个参数来选择班次数?如果我想移动两列、三列或四列而不是一列。
这里有两种可能的解决方案,如果你愿意,可以把它们包装成一个函数。
第一个解决方案的理念是转置您的数据集并将行用作列,这样您就可以使用 mutate_at
(您随机选择的行)然后再次转置:
dt <- read.table(text = "
0 344 34 0 0
0 350 16 0 0
0 366 11 0 0
0 376 8 0 0
0 380 28 0 0
0 397 55 0 0
0 398 45 0 0
0 400 19 0 0
0 402 30 0 0")
library(tidyverse)
# for reproducibility
set.seed(4)
# pick number of rows to shift
num_rows = round(1/3 * nrow(dt))
# sample position of those rows
rows = sample(1:nrow(dt), num_rows)
# specify number of shifts
num_shifts = 2
t(dt) %>% # transpose dataset
data.frame() %>% # update to data frame
mutate_at(rows, ~lag(., num_shifts, default = 0L)) %>% # use the selected row positions and the selected number of shifts to apply this function
t() %>% # transapose data again
data.frame(., row.names = NULL) # update to dataframe
# X1 X2 X3 X4 X5
# 1 0 0 0 344 34
# 2 0 350 16 0 0
# 3 0 0 0 366 11
# 4 0 376 8 0 0
# 5 0 380 28 0 0
# 6 0 0 0 397 55
# 7 0 398 45 0 0
# 8 0 400 19 0 0
# 9 0 402 30 0 0
另一种方法,无需转置,但使用 map2
:
处理行
dt %>%
group_by(id = row_number()) %>% # group by row id
nest() %>% # nest data
mutate(d = map2(id, data, ~if(.x %in% rows) lag(.y, num_shifts, default = 0L) else .y)) %>% # apply shift to selected row positions/ids
unnest(d) %>% # unnest data
select(-id, -data) # remove unnecessary columns
# # A tibble: 9 x 5
# V1 V2 V3 V4 V5
# <int> <int> <int> <int> <int>
# 1 0 0 0 344 34
# 2 0 350 16 0 0
# 3 0 0 0 366 11
# 4 0 376 8 0 0
# 5 0 380 28 0 0
# 6 0 0 0 397 55
# 7 0 398 45 0 0
# 8 0 400 19 0 0
# 9 0 402 30 0 0
我有一个数据框:
dt <- read.table(text = "
0 344 34 0 0
0 350 16 0 0
0 366 11 0 0
0 376 8 0 0
0 380 28 0 0
0 397 55 0 0
0 398 45 0 0
0 400 19 0 0
0 402 30 0 0")
我想将 1/3 的行随机向右移动一列,例如:
dt1 <- read.table(text = "
0 344 34 0 0
0 350 16 0 0
0 0 366 11 0
0 376 8 0 0
0 0 380 28 0
0 0 397 55 0
0 398 45 0 0
0 400 19 0 0
0 402 30 0 0")
是否可以有一个参数来选择班次数?如果我想移动两列、三列或四列而不是一列。
这里有两种可能的解决方案,如果你愿意,可以把它们包装成一个函数。
第一个解决方案的理念是转置您的数据集并将行用作列,这样您就可以使用 mutate_at
(您随机选择的行)然后再次转置:
dt <- read.table(text = "
0 344 34 0 0
0 350 16 0 0
0 366 11 0 0
0 376 8 0 0
0 380 28 0 0
0 397 55 0 0
0 398 45 0 0
0 400 19 0 0
0 402 30 0 0")
library(tidyverse)
# for reproducibility
set.seed(4)
# pick number of rows to shift
num_rows = round(1/3 * nrow(dt))
# sample position of those rows
rows = sample(1:nrow(dt), num_rows)
# specify number of shifts
num_shifts = 2
t(dt) %>% # transpose dataset
data.frame() %>% # update to data frame
mutate_at(rows, ~lag(., num_shifts, default = 0L)) %>% # use the selected row positions and the selected number of shifts to apply this function
t() %>% # transapose data again
data.frame(., row.names = NULL) # update to dataframe
# X1 X2 X3 X4 X5
# 1 0 0 0 344 34
# 2 0 350 16 0 0
# 3 0 0 0 366 11
# 4 0 376 8 0 0
# 5 0 380 28 0 0
# 6 0 0 0 397 55
# 7 0 398 45 0 0
# 8 0 400 19 0 0
# 9 0 402 30 0 0
另一种方法,无需转置,但使用 map2
:
dt %>%
group_by(id = row_number()) %>% # group by row id
nest() %>% # nest data
mutate(d = map2(id, data, ~if(.x %in% rows) lag(.y, num_shifts, default = 0L) else .y)) %>% # apply shift to selected row positions/ids
unnest(d) %>% # unnest data
select(-id, -data) # remove unnecessary columns
# # A tibble: 9 x 5
# V1 V2 V3 V4 V5
# <int> <int> <int> <int> <int>
# 1 0 0 0 344 34
# 2 0 350 16 0 0
# 3 0 0 0 366 11
# 4 0 376 8 0 0
# 5 0 380 28 0 0
# 6 0 0 0 397 55
# 7 0 398 45 0 0
# 8 0 400 19 0 0
# 9 0 402 30 0 0