Создание функции, зацикливающейся на каждой строке в R - PullRequest
0 голосов
/ 04 мая 2020

Я хочу написать функцию, которая создает новый столбец со строками для столбцов 1-3, только в том случае, если было получено более 2 вопросов для столбцов 1-3 в строке , в противном случае выведите «N».

Вот мой фрейм данных:

test <- data.frame(Manager1 = c(1, 3, 3), Manager2 = c(3, 4, 1), Manager3 = c(NA , 4, 2), Team1 = c(3, 4, 1))

Желаемый вывод:

Manager1 Manager2 Manager3 Team1 mean_score
    1       3                3        N
    3       4        4       4     3.66667
    3       1        2       1        2

Мой код выглядит следующим образом, но он не работает:

#create function
mean_score <- function(x) {
  for (i in 1:nrow(test)){
    if (sum(test[i, x] != "NA", na.rm = TRUE) >2){
      test$mean_score[i] <- rowMeans(test[i, x], na.rm = TRUE)
    } else 
      test$mean_score[i] <- print("N")
  }
}

#compute function
mean_score(1:3)

Что мне не хватает? Также приветствуются предложения по улучшению кода.

Ответы [ 3 ]

1 голос
/ 04 мая 2020

Хотя у GKi есть лучший ответ, который более прост и который вы должны использовать здесь, я изменил ваш код, чтобы он работал.

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

Также вам не нужно использовать print() для вставки символа в вектор.

Надеюсь, это поможет объяснить, почему у вашей функции были проблемы, но, честно говоря, ответ GKi лучше для общего использования R!

mean_score <- function(x) {
  mean_score <- vector()
  for (i in 1:nrow(x)){
    if (sum(x[i,] != "NA", na.rm = TRUE) >3){
      mean_score[i] <- rowMeans(x[i,], na.rm = TRUE)
    } else 
      mean_score[i] <- "N"
  }
  x$mean_score <- mean_score
  return(x)
}

mean_score(test)
1 голос
/ 04 мая 2020

Я думаю, что не стоит объединять символ со значением числительного c, поскольку он преобразует весь столбец в символ. Однако, если это то, что вы хотите:

my_sum <- function(x,min=2){
  s <- mean(x, na.rm = T) # get the mean
  no_na <- sum(!is.na(x)) # count the number of non NAs
  if(no_na>min){s}else{"N"} # return mean if enough non NAs
}
test$mean <- apply(test[,1:3],1,my_sum)

test

  Manager1 Manager2 Manager3 Team1             mean
1        1        3       NA     3                N
2        3        4        4     4 3.66666666666667
3        3        1        2     1                2

str(test)
'data.frame':   3 obs. of  5 variables:
 $ Manager1: num  1 3 3
 $ Manager2: num  3 4 1
 $ Manager3: num  NA 4 2
 $ Team1   : num  3 4 1
 $ mean    : chr  "N" "3.66666666666667" "2"
1 голос
/ 04 мая 2020

Вы можете просто использовать rowMeans, что будет возвращать NA, если в одной строке содержится NA, что должно быть здесь эквивалентно , только если ответили более чем на 2 вопроса для столбцов 1-3 в строке .

test$mean_score <- rowMeans(test[,1:3])
#  Manager1 Manager2 Manager3 Team1 mean_score
#1        1        3       NA     3         NA
#2        3        4        4     4   3.666667
#3        3        1        2     1   2.000000
...