R для l oop сквозных векторов, если индекс вне пределов изменяется на определенное значение - PullRequest
1 голос
/ 12 июля 2020

У меня есть векторный список, в котором иногда значения варьируются от 1 до 7, а иногда от 1 до 5. Я хочу пройти через них l oop и получить подсчет частоты с помощью функции table, а затем поместить эти значения во фрейм данных , но я получаю сообщение об ошибке subscript out of bounds. Он делает это, потому что ожидает значение integer. Когда это произойдет, я хотел бы установить целочисленное значение на 0.

Есть ли простая функция, которую я мог бы обернуть вокруг значения integer, например somefunction(t[[6]]), которая возвращает 0?

#list of vectors, the first has values 1 to 7, the second has 1 to 5, 
#the third is 1 to 7 again and is only included to show that my real problem has many
# more vectors to evaluate


vectors<-list(c(1,1,2,2,3,3,3,4,4,5,5,5,6,6,6,6,7,7,7,7,7),
c(1,1,2,2,3,3,3,4,4,5,5,5,5,5,5,5,5,5,5,5,5),
c(1,1,2,2,3,3,3,4,4,5,5,5,6,6,6,6,7,7,7,7,7))

#empty data frame
df<-data.frame()
#loop through list of vectors and get frequncy count per list
for (i in 1:length(vectors)) {
  #count frquency of each value as variable t
  t<-table(vectors[[i]])
      #put frequency count of each value in the data frame - the problem is 
      #that in the second vector, there are only values of 1 to 5, so t[[6]] 
      #reports "subscript out of bounds". I want to change this to a value of 0
  df<-rbind(df,cbind(t[[1]],t[[2]],t[[3]],t[[4]],t[[5]],t[[6]],t[[7]]))
}

df

1 Ответ

1 голос
/ 12 июля 2020

Вместо цикла мы можем преобразовать list в двухстолбцовую data.frame с stack после установки имен list, а затем применить table

table(stack(setNames(vectors, seq_along(vectors)))[2:1])
#  values
#ind  1  2  3  4  5  6  7
#  1  2  2  3  2  3  4  5
#  2  2  2  3  2 12  0  0
#  3  2  2  3  2  3  4  5

выше будет объект table. Если нам нужно преобразовать в data.frame (без преобразования в «длинный» формат)

as.data.frame.matrix(table(stack(setNames(vectors, seq_along(vectors)))[2:1]))

Здесь мы применяем table только один раз, и это будет более эффективно и менее сложно, потому что оно автоматически находит уникальные ценности. Если мы зацикливаемся, то мы должны заранее найти уникальные значения, чтобы добавить недостающие уровни, которые будут считаться как 0

С помощью al oop мы можем преобразовать отдельные элементы list в factor, указав levels как unique всех элементов

un1 <- sort(unique(unlist(vectors)))
t(sapply(vectors, function(x) table(factor(x, levels = un1))))

В for l oop мы могли бы использовать rbind, но с rbind можно было бы ожидать, что имена столбцов будут такими же или длина будет одинаковой. Таким образом, вместо rbind можно указать bind_rows из dplyr

library(dplyr)
df <- data.frame()
for(i in seq_along(vectors)) {
      tbl1 <- table(vectors[[i]])
      df <- bind_rows(df, tbl1)
 }

По умолчанию bind_rows заполняется NA для столбцов, которые не найдены. Затем мы заменяем NA на 0

df[is.na(df)] <- 0

Но это не эффективный вариант, как показано при вызове table один раз

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...