Замена значений в нескольких столбцах значениями из тех же столбцов в разных строках в зависимости от условий

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

Сокращенный пример моих данных выглядит так:

data <- data.frame(cbind(
          id=c(1:7),
          set = c(1,2,2,3,1,3,2),
          choice = c("A1","A2","A1","A1","A2","A2","A2"),
          parameter1=c("blue","green","red","red","orange","blue","green"),
          parameter2=c("low", "low","high","medium","high","high","low")
          ))

data

  id set choice parameter1 parameter2
1  1   1     A1       blue        low
2  2   2     A2      green        low
3  3   2     A1        red       high
4  4   3     A1        red     medium
5  5   1     A2     orange       high
6  6   3     A2       blue       high
7  7   2     A2      green        low

Конкретно, я пытаюсь заменить значения параметра 1 и параметра 2 для набора значениями параметра 1 и параметра 2 того же набора, но с другим выбором. Итак, для первой строки set = 1 и selection = A1 я хочу заменить параметр 1 и параметр 2 значениями из строки 5, так как это тот же набор (= 1), но альтернативный выбор (A2).

У меня есть больше параметров и наборов в полном наборе данных, поэтому решение должно быть обобщаемым для большего количества параметров и наборов выбора. Кроме того, при необходимости наборы и соответствующие варианты выбора появляются несколько раз, но всегда с одними и теми же значениями параметров.

Я знаю, что мог бы написать все это с различными условиями if, но это было бы подвержено ошибкам (и совсем не весело). Может быть, у кого-то есть идея, как это сделать по-умному?

(Это мой первый вопрос здесь, надеюсь, что он имеет смысл и достаточно ясен).

РЕДАКТИРОВАТЬ для уточнения: я хочу заменить значения Set 1, A2 значениями Set 1, A1 и наоборот, при этом количество наблюдений останется прежним. Желаемый результат будет выглядеть так:

  id set choice  parameter1 parameter2
1  1   1     A1      orange       high  
2  2   2     A2         red       high
3  3   2     A1       green        low
4  4   3     A1        blue       high 
5  5   1     A2        blue        low
6  6   3     A2         red     medium
7  7   2     A2         red       high

person JFJ    schedule 10.04.2020    source источник
comment
И значения parameter1 и parameter2 строки 5 должны измениться на строку 1? Для более чем 2 choice как вы решаете, какие значения строк следует поменять местами,   -  person Ronak Shah    schedule 10.04.2020
comment
Следовало уточнить это. Данные взяты из эксперимента по выбору, в котором участники всегда выбирают одну из двух альтернатив, поэтому всегда есть только 2 варианта.   -  person JFJ    schedule 10.04.2020


Ответы (2)


Это должно работать с вашими образцами данных и в большем масштабе. Ваши данные:

data <- data.frame(cbind(
  id=c(1:7),
  set = c(1,2,2,3,1,3,2),
  choice = c("A1","A2","A1","A1","A2","A2","A2"),
  parameter1=c("blue","green","red","red","orange","blue","green"),
  parameter2=c("low", "low","high","medium","high","high","low")
),stringsAsFactors = FALSE)

Р-код:

Сначала мы создаем ключ в первой таблице, объединяя набор столбцов и выбор. В соответствии с вашими ожиданиями создаем еще одну таблицу, в которой генерируем ключ для соединения 2-х таблиц (используем substr и один ifelse). Затем мы соединяем две таблицы, сохраняя уникальные идентификаторы и удаляя помощники столбцов.

library(stringi)
library(dplyr)
    data$new3=paste0(data$set,data$choice)
    df=data[,1:3]
    df$new=stri_sub(df$choice,-1,-1)
    df$new2=ifelse(df$new==1,2,1)
    df$new3=paste0(df$set,stri_sub(df$choice,1,1),df$new2)
    df %>% left_join(select(data, starts_with("parameter"),new3), by = "new3") %>% 
      distinct(id,.keep_all = TRUE) %>%
      select(-starts_with("new"))

Выход :

  id set choice parameter1 parameter2
1  1   1     A1     orange       high
2  2   2     A2        red       high
3  3   2     A1      green        low
4  4   3     A1       blue       high
5  5   1     A2       blue        low
6  6   3     A2        red     medium
7  7   2     A2        red       high
person E.Wiest    schedule 10.04.2020

База R (близкое решение):

# Take a subset of the unique ids and sets: params_inverted => data.frame
params_inverted <- unique(data[,c("set", "choice")])

# Invert the choices: levels(data$choice) => factor levels
levels(data$choice) <- rev(levels(data$choice))

# Merge with the original data.frame: params_inverted => data.frame
params_inverted <- merge(
  params_inverted,
  data[, c("set", "choice", grep("param", names(data), value = TRUE))],
  by = c("set", "choice"),
  all.x = TRUE
)

Данные:

data <- data.frame(cbind(
  id=c(1:7),
  set = c(1,2,2,3,1,3,2),
  choice = c("A1","A2","A1","A1","A2","A2","A2"),
  parameter1=c("blue","green","red","red","orange","blue","green"),
  parameter2=c("low", "low","high","medium","high","high","low")
))
person hello_friend    schedule 10.04.2020
comment
Спасибо, что нашли время ответить. Код выше, к сожалению, приводит к набору данных, отличному от того, что я искал. Я отредактировал свой вопрос, чтобы включить желаемый результат. - person JFJ; 10.04.2020
comment
@JuergenF, пожалуйста, проверьте мой отредактированный ответ. Это почти то, что вы хотите, я думаю. Если вы считаете это полезным, пожалуйста, проголосуйте за него, и если он отвечает на ваш вопрос, пожалуйста, примите его. - person hello_friend; 10.04.2020