Правильная итерация с пользовательской функцией в R

#r #xml #list #for-loop

#r #xml #Список #для цикла

Вопрос:

 ## for individual files
input_files <- list.files("U:/tmp", pattern = "[.]xml")
out <- list()
 
# loop for reading input and writing an output
for(i in 1:length(input_files)){
  df0 <- fxml_importXMLFlat(input_files[i])
  df1 <- fxml_toDataFrame(df0, siblings.of=1, elem.or.attr="elem",col.attr = elem.)
}
  

Библиотека flatxml / fxml просто выполняет некоторый синтаксический анализ xml, поэтому игнорируйте это. Что я делаю, так это считываю XML-файлы U/tmp , помещаю их в список, затем для каждого элемента в этом списке запускаю операцию flatxml.

Вывод для каждого файла представляет собой одну строку (показанную в коде как df0 ).

Как я могу взять output ( df0 ), который перезаписывается на каждой итерации, и сохранить его как фрейм данных или список, который будет увеличиваться на одну строку при каждом запуске функции? Разве нет какой-то логики типа i 1, которая делает это?

Для воспроизводимости, вот список, который я прочитал и обработал:

 x
1   SAFETY1007L.xml
2   SAFETY1008L.xml
3   SAFETY10029.xml
4   SAFETY1000V.xml
  

И после запуска importXMLFlat ( df0 ), вот окончательный dataframe ( df1 ) Обратите внимание, что это всего 1 строка, поэтому в итоговой таблице данных будет 4 строки — по одной для каждого элемента в списке inpt :

 REPORTTIMESTAMP
AGENCYIDENTIFIER
AGENCYNAME
1   2019-06-02T07:08:01.751236  California  Culver City Police Department
  

Спасибо за любые идеи.

Ответ №1:

на самом деле у вас довольно много вариантов

  1. вы можете использовать magic_for библиотеку

инициализация

 magicfor::magic_for(print, progress=T, silent=T) # initialisation with print
for(i in 1:length(input_files)){
  df0 <- fxml_importXMLFlat(input_files[i])
  df1 <- fxml_toDataFrame(df0, siblings.of=1, elem.or.attr="elem",col.attr = elem.)
  print(df1) # important for magic_for as expressed ininitialisation
}
magic_result # or magic_result_as_dataframe() or magic_result_as_vector
  
  1. вы можете создать глобальную переменную для добавления вашего df (кажется, вы пытаетесь сделать это только внутри цикла с df1<-c(df0, ), но поскольку вы не сохраняете ее в глобальную переменную, она перезаписывается

     df<-data.frame() # global variable
         for(i in 1:length(input_files)){
           df0 <- fxml_importXMLFlat(input_files[i])
           df1 <- fxml_toDataFrame(df0, siblings.of=1, elem.or.attr="elem",col.attr = elem.)
         df<-c(df, df1)
         }
      
  2. вы могли бы использовать lapply / sapply, просто поставив

     result<-lapply(input_files, fxml_importXMLFlat)  # i used lapply for lists - sapply does the same for data.frames
      

я уверен, что есть еще больше способов сделать это, но из головы я бы предложил вариант 3