Sergio Henriques
Sergio Henriques

Reputation: 135

Apply a function to a set of .csv with similar names

I wish to apply a really simple function in R

BasicFun <- function(x) {
  c(min = min(x), max = max(x), 
    mean = mean(x))
}

To a specific column called "Values" always present in a set of .csv files, all with very similar names (basedata10people.csv, basedata20people.csv, etc...), these names follow:

seq(10, 300, by=10)

So I am looking to do something like:

names <- seq(10, 300, by=10)    
for (i in 1:names) {    
 {    
 file[[i]] = read.csv(file=paste("basedata", [[i]], "people", sep=""))    
 a=BasicFun(file[[i]]$Values)    
 results[[i]] = rbind(a)    
  }    
  allresults = rbindlist(results)    
  write.csv(allresults, file=paste("allresults.csv", sep=""))    
}    

With the aim to compile all those results in a single .csv, that would look something like:

 file min max mean     
 10   30  80   52    
 20   27  89   60    
 30   25  91   50 

Any help or advise will be greatly appreciated.

Upvotes: 0

Views: 61

Answers (1)

AndS.
AndS.

Reputation: 8110

I think you can do this without any loops.

First I set up some dummy data and put it in a folder:

list.files("~/Desktop/test_data")
[1] "basedata10people.csv"   "basedata20people.csv"   "basedata30people.csv" 
[4] "not_csv.txt"            "not_the_right_name.csv"

Next we only select the files you want:

list.files("~/Desktop/test_data", "basedata\\d+.*?.csv")
[1] "basedata10people.csv" "basedata20people.csv" "basedata30people.csv"

Then we set up a dataframe with the files, nest the data, and extract the desired values.

library(tidyverse)
data_frame(files = list.files("~/Desktop/test_data", "basedata\\d+.*?.csv")) %>%
    mutate(files = paste0("~/Desktop/test_data/", files),
        data = invoke_map(read_csv, files),
        min = map(data, ~min(.x$value)),
        max = map(data, ~max(.x$value)),
        mean = map(data, ~mean(.x$value))) %>%
    select(-data) %>%
    unnest()
#   files                                      min   max  mean
# 1 ~/Desktop/test_data/basedata10people.csv     2    51  17.8
# 2 ~/Desktop/test_data/basedata20people.csv     2    51  18  
# 3 ~/Desktop/test_data/basedata30people.csv     1   123  32.2

If you wanted to use your function, you could also do that.

data_frame(files = list.files("~/Desktop/test_data", "basedata\\d+.*?.csv")) %>%
    mutate(files = paste0("~/Desktop/test_data/", files),
        data = invoke_map(read_csv, files),
        vals = map(data, ~BasicFun(.x$value)))%>% 
    unnest(vals %>% map(broom::tidy)) %>% 
    spread(names, x)
#   files                                      max  mean   min
# 1 ~/Desktop/test_data/basedata10people.csv    51  17.8     2
# 2 ~/Desktop/test_data/basedata20people.csv    51  18       2
# 3 ~/Desktop/test_data/basedata30people.csv   123  32.2     1

UPDATE:

Here we change the file names to numbers

data_frame(files = list.files("~/Desktop/test_data", "basedata\\d+.*?.csv")) %>%
    mutate(files = paste0("~/Desktop/test_data/", files),
        data = invoke_map(read_csv, files),
        vals = map(data, ~BasicFun(.x$value)))%>% 
    unnest(vals %>% map(broom::tidy)) %>% 
    spread(names, x) %>%
    mutate(files = as.numeric(str_extract(files, "(?<=basedata)\\d+(?=people)")))
#   files max  mean   min
# 1 10    51  17.8     2
# 2 20    51  18       2
# 3 30   123  32.2     1

Upvotes: 2

Related Questions