Загрузите несколько файлов .csv в R, отредактируйте их и сохраните как новые файлы .csv, названные списком строк символов - PullRequest
0 голосов
/ 26 марта 2020

Я довольно плохо знаком с R и программированием, поэтому приношу извинения, если этот вопрос был задан в другом месте.

Я пытаюсь загрузить несколько файлов .csv, отредактировать их и снова сохранить. Но не могу узнать, как управлять более чем одним CSV-файлом, а также называть новые файлы на основе списка символьных строк.

Итак, у меня есть файл .csv, и я могу сделать:

species_name<-'ace_neg'

{species<-read.csv('species_data/ace_neg.csv')

species_1_2<-species[,1:2]

species_1_2$species<-species_name

species_3_2_1<-species_1_2[,c(3,1,2)]

write.csv(species_3_2_1, file='ace_neg.csv',row.names=FALSE)}

Но я хотел бы запустить этот код для всех файлов .csv в папке и добавить текст в новый столбец на основе Имя файла .csv.

Таким образом, я могу загрузить все файлы .csv и составить список строк символов для использования в качестве нового текста столбца и новых имен файлов.

NDOP_files <- list.files(path="species_data", pattern="*.csv$", full.names=TRUE, recursive=FALSE)

short_names<- substr(NDOP_files, 14,20)

Затем я попробовал:

lapply(NDOP_files, function(x){
  species<-read.csv(x)
  species_1_2<-species[,1:2]
  species_1_2$species<-'name' #don't know  how to insert first character string of short_names instead of 'name', than second character string from short_names for second csv. file etc. 

Затем продолжить в коде, чтобы изменить порядок столбцов

species_3_2_1<-species_1_2[,c(3,1,2)]

И затем написать все новые измененные CSV. файлы и присвойте им имена в списке коротких имен.

Извините, если текст несколько сбивает с толку.

Любая помощь или предложения будут полезны.

Ответы [ 2 ]

1 голос
/ 26 марта 2020

Вы на самом деле довольно близки, и использование lapply() действительно хорошая идея. Как вы заявляете, проблема в том, что в качестве аргумента требуется только один list, но вы хотите работать с двумя. mapply() - это функция в base R, в которую можно вводить несколько списков и циклически переключаться между ними. lapply() и mapply() оба предназначены для создания / манипулирования объектами в R, но вы хотите записать файлы и не заинтересованы в выводе в R. В пакете purrr есть функции walk*()\, которые полезны, когда вы хотите циклически проходить по спискам и заинтересованы только в создании побочных эффектов (в вашем случае сохранение файлов).

purrr::walk2() занимает два списка , так что вы можете предоставить данные и имена файлов одновременно.

library(purrr)

Сначала я создаю некоторые примеры данных (я в основном уже использую здесь ту же концепцию, что и ниже):

test_data <- map(1:5, ~ data.frame(
  a = sample(1:5, 3),
  b = sample(1:5, 3),
  c = sample(1:5, 3)
))
walk2(test_data,
      paste0("species_data/", 1:5, "test.csv"),
      ~ write.csv(.x, .y))

Вместо того, чтобы получить пути к файлам и затем убрать путь, чтобы получить имена файлов, я просто вызываю list.files(), один раз с full.names = TRUE и один раз с full.names = FALSE.

NDOP_filepaths <-
  list.files(
    path = "species_data",
    pattern = "*.csv$",
    full.names = TRUE,
    recursive = FALSE
  )

NDOP_filenames <-
  list.files(
    path = "species_data",
    pattern = "*.csv$",
    full.names = FALSE,
    recursive = FALSE
  )

Теперь я передаю два списка в purrr::walk2(). Используя ~ перед фигурными скобками, я могу определить анонимную функцию более элегантно, а затем использовать .x и .y для ссылки на записи первого и второго списка.

walk2(NDOP_filepaths, 
      NDOP_filenames,
      ~ {
        species <- read.csv(.x)
        species <- species[, 1:2]
        species$species <- gsub(".csv", "", .y)
        write.csv(species, .x)
      })

Узнайте больше о purrr на purrr.tidyverse.org .

Кроме того, вы можете просто извлечь имя файла в l oop и придерживаться lapply() или использовать purrr::map() / purrr::walk(), вот так:

lapply(NDOP_filepaths, 
      function(x) {
        species <- read.csv(x)
        species <- species[, 1:2]
        species$species <- gsub("species///|.csv", "", x)
        write.csv(species, gsub("species///", "", x))
      })
1 голос
/ 26 марта 2020
NDOP_files <- list.files(path="species_data", pattern="*.csv$", 
full.names=TRUE, recursive=FALSE)

# Get name of each file (without the extension)

# basename() removes all of the path up to and including the last path seperator
# file_path_sands_ext() removes the .csv extension

csvFileNames <- tools::file_path_sans_ext(basename(NDOP_files))

Затем я написал бы функцию, которая принимает 1 CSV-файл, выполняет некоторые манипуляции с файлом и выводит фрейм данных. Поскольку у вас есть список csv-файлов для использования list.files, вы можете использовать функцию map в пакете purrr для применения вашей функции к каждому CSV-файлу.

doSomething <- function(NDOP_file){
# your code here to manipulate NDOP_file to your liking
return(NDOP_file)

NDOP_files <- map(NDOP_files, ~doSomething(.x))

Наконец, вы можете манипулировать имена файлов, когда вы пишете новые csv-файлы, используя csvFileNames и пользовательскую функцию, которую вы пишете, чтобы изменить имя файла по своему вкусу По сути, используйте ту же архитектуру определения своей пользовательской функции и использования карты для применения к каждому из ваших файлов.

...