Почему этот цикл for не заполняет новый фрейм данных должным образом? - PullRequest
0 голосов
/ 10 июля 2019

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

Я попытался использовать серию операторов if else внутри цикла for.

df <- rbind(c("Y", "no", "Often"), c("N", "yes", "always"), c("Y", "yes", 
    "never"))
score <- as.data.frame(matrix(0, nrow = 3, ncol = 3))
t <- 1

for (t in nrow(df)) {

  if (df[t,1] == "Y") {
    score[t,1] <- 2
  } else if (df[t,2] == "yes") {
    score[t,2] <- 2
  } else if (df[t,3] == "always") {
    score[t,3] <- 2
  } else if (df[t,3] == "often") {
    score[t,3] <- 1
  }

  next

}

Я ищу вывод: 2, 0, 1, 0, 2, 2, 2, 2, 0

Я получаю: 0, 0, 0, 0, 0, 0, 2, 0, 0

Ответы [ 3 ]

2 голосов
/ 10 июля 2019

Поскольку t было присвоено единственное значение, равное nrow(df), перед входом в цикл.

Вот переделка вашей (также была исправлена ​​опечатка):

df <- rbind(c("Y", "no", "Often"), 
            c("N", "yes", "always"), 
            c("Y", "yes", "never"))
score <- as.data.frame(matrix(0, nrow = 3, ncol = 3))

for (t in 1:nrow(df)) {

  if (df[t,1] == "Y") {
    score[t,1] <- 2
  } 
  if (df[t,2] == "yes") {
    score[t,2] <- 2
  } 
  if (df[t,3] == "always") {
    score[t,3] <- 2
  } 
  if (df[t,3] == "Often") {
    score[t,3] <- 1
  }
}

score
  V1 V2 V3
1  2  0  1
2  0  2  2
3  2  2  0
1 голос
/ 10 июля 2019

Одним из способов может быть преобразование в коэффициент, установить метки, а затем вернуться к числовому.

matrix(as.numeric(as.character(
  factor(as.vector(df), 
         levels=c("always", "N", "never", "no", "Often", "Y", "yes"),
         labels=c(2, 0, 0, 0, 1, 2, 2)))), 3)
#      [,1] [,2] [,3]
# [1,]    2    0    1
# [2,]    0    2    2
# [3,]    2    2    0

Примечание: Если df - это кадр данных, а не матрица, как в примере, мы должны будем использовать as.vector(as.matrix(df)).

0 голосов
/ 10 июля 2019

Вот несколько способов обхода цикла и if / else структур с использованием dplyr::case_when или dplyr::recode.Обе эти функции обеспечивают векторизованные способы выполнения этой замены.Все параметры здесь имеют одинаковый вывод.

dplyr::recode принимает набор пар ключ-значение с необязательным значением по умолчанию.Он также может принимать именованный список без кавычек !!!, что позволяет сохранить вектор поиска.Используя apply вместо цикла:

library(dplyr)

as.data.frame(apply(df, 1, function(x) {
  recode(x, 
         Y = 2,
         yes = 2,
         always = 2,
         Often = 1,
         .default = 0)
}))
#>   V1 V2 V3
#> 1  2  0  2
#> 2  0  2  2
#> 3  1  2  0

# with a lookup and !!!
lookup <- c(Y = 2, yes = 2, always = 2, Often = 1)

as.data.frame(apply(df, 1, function(x) recode(x, !!!lookup, .default = 0)))

Вы также можете сделать эти методы путем перекодирования, преобразования в матрицу, а затем преобразования в фрейм данных (аналогично приведенному ниже).

Другой вариант - dplyr::case_when, который похож на векторизованный оператор switch.Одним из преимуществ здесь является то, что, поскольку у вас есть несколько значений, заменяемых на 2, вы можете использовать %in% вместо повторения.

as.data.frame(matrix(case_when(
  df %in% c("Y", "yes", "always") ~ 2,
  df == "Often" ~ 1,
  T ~ 0
), nrow = 3, ncol = 3))

Наконец, dplyr::mutate_all позволяет вам использовать recode во всех столбцахпосле преобразования во фрейм данных.

mutate_all(as.data.frame(df), recode, !!!lookup, .default = 0)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...