Переименование элементов списка, содержащих фрейм данных, с использованием первой записи столбца фрейма данных

#r #list

Вопрос:

У меня есть следующие данные:

 dataset = list()
a <- c(1,2,3)
b <- c(1,2,3)
country <- c("A","B","C")
source_country <-  c("D","D","D")
dataset[[1]] <- data.frame(a,b,country, source_country)
a <- c(NA)
b <- c(NA)
country <- c(NA)
source_country <- c(NA)
dataset[[2]] <- data.frame(a,b,country, source_country)
 

введите описание изображения здесь

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

 for (i in 1:length(dataset)) {
   if (!is.null(dataset[[i]])) {
    print ("no data") 
  } else if (nrow(dataset[[i]]) > 1) {
    names(dataset)[i] <- dataset[[i]][["source_country"]][[1]]
  }   
}
 

Но, похоже, это не работает..

Желаемый Результат:

 names(dataset)[1] <- "D"
names(dataset)[2] <- "NA"
 

введите описание изображения здесь

Ответ №1:

Один purrr из вариантов —

 library(purrr)

set_names(dataset, map_chr(dataset, pluck, "source_country", 1))

#$D
#  a b country source_country
#1 1 1       A              D
#2 2 2       B              D
#3 3 3       C              D

#

lt;NA>
# a b country source_country
#1 NA NA NA NA

Ответ №2:

Если ваша R версия меньше 4.1.0, замените (x) ее на function(x) :

 names(dataset) <- sapply(dataset, (x) x$source_country[1])
 

Это даст вашему второму элементу имя NA . Если вы хотите, чтобы это был символ, который вы можете обернуть с помощью функции as.character .


Проблема с вашим циклом заключается в том, что вы проверяете, не является ли каждый элемент вашего списка нулевым ( is.null проверяет, является ли элемент нулевым, !is.null инвертирует это). Поскольку каждый элемент вашего списка является фреймом данных, ни один из них не является нулевым, поэтому ваш цикл никогда не входит в else if предложение. Единственное, что вы делаете в своем if заявлении, — это печатаете, чтобы ничего не переименовывалось.

Вы могли бы сделать что-то вроде:

 for (i in 1:length(dataset)) {
  if (nrow(dataset[[i]]) == 0) {
    print ("no data") 
  } else if (nrow(dataset[[i]]) >= 1) {
    names(dataset)[i] <- dataset[[i]][["source_country"]][1]
  }   
}
 

Ответ №3:

С помощью base R

 setNames(dataset,   unlist(sapply(dataset, subset, 
   subset = seq_along(source_country) == 1, select = source_country)))
 

-уптут

 $D
  a b country source_country
1 1 1       A              D
2 2 2       B              D
3 3 3       C              D



lt;NA>
a b country source_country
1 NA NA NA NA