Построение фрейма данных строка за строкой из списка

#json #r #dataframe

#json #r #фрейм данных

Вопрос:

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

 [
  { 'firstName': 'abc', 'lastName' : 'def' },
  { 'firstName': 'abc2', 'lastName' : 'def2' }
]
 

Я хочу сохранить эти данные во фрейме данных. Мой текущий подход ошибочен и кажется действительно грязным. У меня есть несколько наборов данных, но мне нужно указать столбцы. Кто-нибудь может предложить что-то «более чистое»?

Проблема 1: Мне нужно указать имена данных

 library(rjson)
listData <- fromJSON(jsonData)
listNames <- c('firstName', 'lastName')

for (player in listData){
  playerCols = c()
  for (name in listNames){
    value <- player[[name]]
    if (is.null(value}{value <- "NA"}
    playerCols <- c(playerCols, value)
  }
  # code to convert playerCols to data.frame currently goes here. 
}
 

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

Проблема 2: кажется, мне не удается добавить строку данных, вместо этого списки создаются в виде столбцов

 for (player in listData){
  # code to extract columns here
  df = data.frame(playerCols, name=listNames)
  print(df)
}
 

Вместо создания фрейма данных из 2 столбцов со строками, содержащими все данные и все имена, мне нужна одна строка с именованными столбцами, которые я затем могу rbind объединить.

Ответ №1:

Почти всегда это плохая идея — пытаться построить data.frame построчно. Это просто неэффективный процесс. Лучше строить свои данные по столбцам и объединять их в data.frame в конце. Во-первых, давайте воспользуемся некоторыми примерами данных, которые на самом деле содержат пропущенные значения, как вы описали

 a<-'[
  { "firstName": "abc", "lastName" : "def" },
  { "firstName": "abc2" }
]'
 

Давайте также создадим вспомогательную функцию, которая извлечет значение из списка, если оно существует, или вернет NA, если оно не существует

 extr<-function(list,ele) {
    x<-list[[ele]]
    if (is.null(x)) x=NA;
    x
}
 

Если вы хотите получить все значения без явного указания имен тегов, вы можете найти их с помощью

 listNames <- unique(unlist(lapply(listData, names)))
 

Теперь мы можем преобразовать json в список, а затем каждый раз извлекать вектор значений столбцов и, наконец, объединять их в data.frame с помощью

 listData <- fromJSON(a)
data.frame(Map(function(n) sapply(listData, extr, n), listNames))
 

Здесь я использую Map , а не более привычный lapply , потому что он будет правильно использовать значения listNames в качестве имен для возвращаемого списка.

Комментарии:

1. Идеально, что сработало, за одним исключением — c(sapply(listData, names)) вместо использования unlist