Заменить значения в наборе столбцов на основе условия - PullRequest
1 голос
/ 07 марта 2019

У меня есть такой фрейм данных

id  v1  v2  v3  v4  v5  pos
1   11  12  11  10  10  3
2   17  11  22  40  23  4
1   11  22  50  10  10  2

Я бы хотел изменить его значения на основе условия, связанного с pos, чтобы получить:

id  v1  v2  v3  v4  v5  pos
1   11  12  12  12  12  3
2   17  11  22  22  22  4
1   11  11  11  11  11  2

Так что в основном значения получают предыдущийзначение и переменная pos определяет, откуда мы должны начать.

Thx!

Ответы [ 3 ]

2 голосов
/ 07 марта 2019

Подход, использующий некоторое индексирование, которое должно быть эффективным во время выполнения.
Однако не очень эффективный с точки зрения памяти, поскольку делает копию того же размера, что и входные данные:

vars <- paste0("v",1:5)
nv <- dat[vars][cbind(seq_len(nrow(dat)), dat$pos-1)]
ow <- col(dat[vars]) >= dat$pos
dat[vars][ow] <- nv[row(ow)[ow]]

#  id v1 v2 v3 v4 v5 pos
#1  1 11 12 12 12 12   3
#2  2 17 11 22 22 22   4
#3  1 11 11 11 11 11   2

Пояснение:

Получить интересующие переменные:

vars <- paste0("v",1:5)

Получить новые значения для перезаписи для каждой строки:

nv <- dat[vars][cbind(seq_len(nrow(dat)), dat$pos-1)]

Сделать логическую матрицу ячеек для перезаписи

ow <- col(dat[vars]) >= dat$pos

Перезапишите ячейки, используя идентификатор строки, чтобы выбрать подходящее значение.

dat[vars][ow] <- nv[row(ow)[ow]]

Быстрая сравнительная синхронизация с использованием большего набора данных:

dat <- dat[rep(1:3,1e6),]

# indexing
#   user  system elapsed 
#   1.36    0.31    1.68 

# apply
#   user  system elapsed 
#  77.30    0.83   78.41 

# gather/spread
#   user  system elapsed 
# 293.43    3.64  299.10
1 голос
/ 07 марта 2019

Использование apply от базы R

data.frame(t(apply(df, 1, function(x) 
     c(x[1:x["pos"]], rep(x[x["pos"]], ncol(df) - x["pos"] - 2), x['pos']))))

#  X1 X2 X3 X4 X5 X6
#1  1 11 12 12 12  3
#2  2 17 11 22 22  4
#3  1 11 11 11 11  2
1 голос
/ 07 марта 2019

Вот одна идея с gather и spread.

library(tidyverse)

dat2 <- dat %>%
  rowid_to_column() %>%
  gather(v, value, starts_with("v")) %>%
  group_by(rowid) %>%
  mutate(value = ifelse(row_number() >= (pos - 1), nth(value, (pos - 1)[[1]]), value)) %>%
  spread(v, value) %>%
  ungroup() %>%
  select(names(dat))

dat2
# # A tibble: 3 x 7
#      id    v1    v2    v3    v4    v5   pos
#   <int> <int> <int> <int> <int> <int> <int>
# 1     1    11    12    12    12    12     3
# 2     2    17    11    22    22    22     4
# 3     1    11    11    11    11    11     2

ДАННЫЕ

dat <- read.table(text = "id  v1  v2  v3  v4  v5  pos
1   11  12  11  10  10  3
2   17  11  22  40  23  4
1   11  22  50  10  10  2",
                  header = TRUE)
library(tidyverse)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...