2 votes

Comment obtenir les attributs des éléments d'une liste de manière récursive dans R ?

J'ai un fichier imbriqué list dont certains éléments (pas tous) ont des attributs que je veux conserver (j'ai converti une sortie xml en une structure de type list ). J'essaie de l'aplatir dans une data.frame . La structure est la suivante :

myList <- structure(list(address = structure(list(Address = list(Line = list("xxxxxxx"), 
                                          Line = list("xxxxxxx"), Line = list("xxxxxxx"), PostCode = list(
                                            "XXX XXX"))), type = "Residential", verified = "Unverified"), 
amount = structure(list(paymentAmount = list(maxAmount = list(
  amountPart = structure(list(Amount = list("0.00")), component = "Standard"), 
  amountPart = structure(list(Amount = list("0.00")), component = "Thing1"), 
  amountPart = structure(list(Amount = list("0.00")), component = "Thing2"), 
  amountPart = structure(list(Amount = list("0.00")), component = "Thing3"), 
  amountPart = structure(list(Amount = list("0.00")), component = "Thing4"), 
  amountPart = structure(list(Amount = list("100.00")), component = "Thing5"), 
  amountPart = structure(list(Amount = list("0.00")), component = "Thing6")), 
  otherAmount = list(Amount = list("0.00")), 
  discount = list("0.00"), 
  transition = list(
    "0.00"), discounts = list(), regularPayment = list(
      "200.00")), 
  paymentInfo = list(income = structure(list(
        net = list("0")), refNumber = "xxxxxxx"))), 
  paymentDate = "2021-03-22", startDate = "2021-02-16", endDate = "2021-03-15")), 
type = "Normal")

J'ai essayé rapply(myList, attributes) mais cela semble juste revenir NULL .

J'ai également essayé d'utiliser une boucle dans une fonction récursive :

get_attributes <- function(myList, attribute_list = NULL) {
  if (is.null(attribute_list)) attribute_list <- list()
  for (i in seq_along(myList)) {
    if (is.list(myList[[i]])) {
      attribute_list <- c(attribute_list, sapply(myList[[i]], attributes))
      attribute_list <- get_attributes(myList[[i]], attribute_list)
    } else {
      attribute_list <- c(attribute_list, attributes(myList[[i]]))
    }
  }
  attribute_list
}

Une fois que j'ai obtenu la liste des attributs, je veux les placer dans une seule ligne. data.frame - quelque chose comme data.frame(address.type = "Residential", address.verified = "Unverified", component.1 = "Standard", component.2 = "Thing1"

La fonction avec une boucle est un peu désordonnée et pas très "R", et elle semble aussi produire beaucoup d'éléments répétés que je ne veux pas. Quelqu'un a-t-il une idée de la façon de mettre en œuvre cette fonction de manière plus élégante ?

UPDATE

J'ai affiné l'implémentation de la boucle comme suit, ce qui semble fonctionner, mais je n'ai pas réussi à trouver comment utiliser l'un ou l'autre des éléments suivants purrr ou l'un des *apply à la place de la boucle :

get_attributes <- function(myList, attribute_list = NULL, prefix = NULL) {

  if (is.null(attribute_list)) {
    attribute_list <- list()
  }
  if (is.null(prefix)) {
    prefix <- ""
  }

  for (i in seq_along(myList)) {
    name <- names(myList)[i]
    attrs <- attributes(myList[[i]])
    if (!is.null(attrs)) {
      names(attrs) <- paste0(prefix, name, ".", names(attrs))
      attrs <- attrs[!grepl("\\.names$", names(attrs))]
      attribute_list <- c(attribute_list, attrs)
    }
    if (is.list(myList[[i]])) {
      attribute_list <- get_attributes(myList[[i]],
                                       attribute_list,
                                       paste0(prefix, name, "."))
    }
  }

  attribute_list

}

do.call(data.frame, get_attributes(myList))

1voto

Ronak Shah Points 24715

Vous pouvez rassembler tous les attributs disponibles et ne garder que ceux qui vous intéressent.

library(purrr)

map_df(myList, ~map_chr(attributes(.x), toString))

#  names                      type        verified   paymentDate startDate  endDate   
#  <chr>                      <chr>       <chr>      <chr>       <chr>      <chr>     
#1 Address                    Residential Unverified NA          NA         NA        
#2 paymentAmount, paymentInfo NA          NA         2021-03-22  2021-02-16 2021-03-15

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X