Манипулировать повторяющимися CSV-файлами в цикле For R

#r #for-loop

#r #цикл for

Вопрос:

спасибо за помощь! Вот описание того, что я делаю.

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

Основной обучающий набор выглядит следующим образом:

     > head(main_train)
    Subject                            Datafile                   Label
1 Subject02 Subject02/Subject02_Aufnahme000.csv         curve-left-step
2 Subject02 Subject02/Subject02_Aufnahme001.csv         curve-left-step
3 Subject02 Subject02/Subject02_Aufnahme002.csv            stand-to-sit
4 Subject02 Subject02/Subject02_Aufnahme003.csv curve-right-spin-Rfirst
5 Subject02 Subject02/Subject02_Aufnahme004.csv            jump-one-leg
6 Subject02 Subject02/Subject02_Aufnahme005.csv   lateral-shuffle-right
  

Мне удалось выполнить итерацию по этим файлам следующим образом:

 csv <- list.files(path = "Subjects/Subject02/", pattern = ".csv", full.names = TRUE)
  

Я хотел бы сначала разделить набор данных на кварталы, извлечь среднее значение, медиану, sd, max и min из каждого столбца кварталов и получить одну строку со значениями mean_1, mean_2, mean_3, mean,_4…

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

Я использую циклы For, но я перепробовал ВСЕ (lapply, sapply, но из тех, у которых есть функции между, …) . Мой результат должен возвращать 440 строк для количества csv-файлов, но в этой версии я получаю только одну строку обратно. Я хотел бы получить некоторую помощь в этом. Кроме того, я думаю, что это интересная дилемма, которая должна быть связана с другими проблемами цикла.

Вот мой код:

 for(i in csv) { 
  dataset <- read.csv(i)

  first = round(nrow(dataset)/4)
  second = 2 * round(nrow(dataset)/4)
  third = 3 * round(nrow(dataset)/4)

  dataset_1 = dataset[1:first,]
  dataset_2 = dataset[first:second,]
  dataset_3 = dataset[second:third,]
  dataset_4 = dataset[third:nrow(dataset),]

  for (v in dataset_1){
    mean_1 = mean(v)
    median_1 = median(v)
    sd_1 = sd(v)
    min_1 = min(v)
    max_1 = max(v)
  }
  for (v in dataset_2){
    mean_2 = mean(v)
    median_2 = median(v)
    sd_2 = sd(v)
    min_2 = min(v)
    max_2 = max(v)
  }
  for (v in dataset_3){
    mean_3 = mean(v)
    median_3 = median(v)
    sd_3 = sd(v)
    min_3 = min(v)
    max_3 = max(v)
  }
  for (v in dataset_1){
    mean_4 = mean(v)
    median_4 = median(v)
    sd_4 = sd(v)
    min_4 = min(v)
    max_4 = max(v)
  }

  subject_data <- cbind(mean_1, mean_2, mean_3, mean_4,
                        median_1, median_2, median_3, median_4,
                        sd_1, sd_2, sd_3, sd_4,
                        min_1, min_2, min_3, min_4,
                        max_1, max_2, max_3, max_4)
}
  

и результат, представляющий собой только одну строку, должен быть равен 440:

     > subject_data
       mean_1   mean_2   mean_3   mean_4 median_1 median_2 median_3 median_4     sd_1     sd_2     sd_3     sd_4 min_1 min_2
[1,] 33280.73 36429.69 35986.18 33280.73    33709    36904    35264    33709 1957.654 1797.988 4484.521 1957.654 29328 32184
     min_3 min_4 max_1 max_2 max_3 max_4
[1,] 22768 29328 38320 38320 46456 38320
  

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

1. Я думаю, что с этой задачей лучше всего справиться с помощью purrr — Вы знакомы с этим пакетом?

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

3. Добро пожаловать. Это также решило вашу проблему с количеством строк?

4. @SteenHarsted Я думаю, что существует серьезная проблема с RStudio и копированием и вставкой. В итоге я буквально перепечатал все слово в слово, и это сработало. Не уверен, почему, и много часов потратил на возню. Но в конечном итоге код заработал в этом смысле.

Ответ №1:

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

Что касается вашего количества строк — я думаю, этот код упростит точное определение любых потенциальных ошибок в ваших данных.

Сначала я создаю некоторые данные, имитирующие вашу структуру. Я создаю всего три csv-файла .

 library(tidyverse)
library(here)

#Create some csv files
curve_left_step = rnorm(16, 0, 1)
stand_to_sit = rnorm(16, 20, 2)
jump_one_leg = rnorm(16, 15, 1)

write.csv(curve_left_step, here("Subject02_Aufnahme000.csv"))
write.csv(stand_to_sit, here("Subject02_Aufnahme002.csv"))
write.csv(jump_one_leg, here("Subject02_Aufnahme004.csv"))
  

Я импортирую эти файлы в R с помощью purrr. Это сохраняет все данные в одном фрейме данных. Я также добавляю столбец label.

 #Import the csv files into R using purrr
data_all <- tibble(
  path = list.files(path = here(), pattern = "Subject", full.names = TRUE)) %>% 
  mutate(
    data = map(.x=path, ~read.csv(file = .x)),
    label = c("curve_left_step", "stand_to_sit", "jump_one_leg"))
  

Преимущество этой структуры данных в том, что вы можете применять функции к небольшим наборам данных (столбцу данных) внутри объекта data_all.

Сначала мы создаем такую функцию:

 #Create a function that splits the data into 4 and keeps a selected quarter
split_and_calc <- function(.data, ...){
  .data %>%
    #Divide into quarters
    mutate(
      quarter = ceiling(row_number()/4)) %>% 
    #Select the quarter of interest  
    filter(quarter == ...) %>%
    #Select the variable of interest. here it is [[2]], but in your data this is likely different
    select(2) %>% 
    summarise_all(.funs = c("mean", "median", "sd", "min", "max"))
}
  

Теперь мы применяем функцию ко всем небольшим фреймам данных в столбце данных:

 #Apply the function to all dataframes in data column in data_all
data_all <- data_all %>% 
  mutate(
    quarter1 = map(.x=data, ~split_and_calc(.x, 1)),
    quarter2 = map(.x=data, ~split_and_calc(.x, 2)),
    quarter3 = map(.x=data, ~split_and_calc(.x, 3)),
    quarter4 = map(.x=data, ~split_and_calc(.x, 4)))


> data_all
# A tibble: 3 x 7
  path                                                          data               label         quarter1           quarter2          quarter3          quarter4         
  <chr>                                                         <list>             <chr>         <list>             <list>            <list>            <list>           
1 C:/Users/sharsted/OneDrive/R/R club/Facebook help/Subject02_~ <data.frame [16 x~ curve_left_s~ <data.frame [1 x ~ <data.frame [1 x~ <data.frame [1 x~ <data.frame [1 x~
2 C:/Users/sharsted/OneDrive/R/R club/Facebook help/Subject02_~ <data.frame [16 x~ stand_to_sit  <data.frame [1 x ~ <data.frame [1 x~ <data.frame [1 x~ <data.frame [1 x~
3 C:/Users/sharsted/OneDrive/R/R club/Facebook help/Subject02_~ <data.frame [16 x~ jump_one_leg  <data.frame [1 x ~ <data.frame [1 x~ <data.frame [1 x~ <data.frame [1 x~
  

Ваши данные из отдельных файлов .csv теперь хранятся в столбце data, в то время как Quarter1 содержит среднее значение, медиану, sd, min и max для 1 квартала данных, а также для quarter2, 3 и 4.

Допустим, теперь вы хотите получить доступ к своим итоговым значениям из quarter1. Вы можете выполнить следующий код:

 data_all %>% 
  select(label, quarter1) %>% 
  unnest()
# A tibble: 3 x 6
  label              mean  median    sd    min    max
  <chr>             <dbl>   <dbl> <dbl>  <dbl>  <dbl>
1 curve_left_step  -0.360  -0.384 0.833  -1.13  0.458
2 stand_to_sit     20.9    21.0   2.09   18.9  22.8  
3 jump_one_leg     14.9    15.0   0.315  14.5  15.2 
  

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

1. Привет @marc_s, что ты имеешь в виду, говоря «выбрать интересующую переменную» и «выбрать (2)»?

2. Привет @MargiSant , в этой строке выбирается один столбец из импортированного csv-файла. Затем этот столбец используется для вычисления нужной вам описательной статистики. В созданных мной данных интересующий столбец является вторым — следовательно select(2) . Я не знаю вашу структуру данных в файле csv, но если у вас есть только один столбец, вы можете пропустить строку выбора.