Інші відповіді показати вам , як зробити список data.frames , коли ви вже маєте купу data.frames, наприклад, d1
, d2
, .... Маючи послідовно іменовані кадри даних є проблемою, і помістивши їх в список є добре виправити, але найкраща практика полягає в тому, щоб уникнути того, що в першу чергу є купа фреймів data.frames .
Інші відповіді дають безліч деталей про те, як призначити кадри даних спискам елементів, отримати доступ до них і т. Д. Ми також трохи це висвітлимо тут, але головний пункт - це сказати , не чекайте, поки у вас буде купа data.frames
щоб додати їх до списку. Почніть зі списку.
У решті цієї відповіді будуть висвітлені деякі поширені випадки, коли вас може спокусити створити послідовні змінні, а також показано, як перейти безпосередньо до списків. Якщо ви новачок у списках на R, ви можете також прочитати, в чому різниця між елементами списку [[
та [
в доступі до них? .
Списки від початку
Ніколи не створюйте d1
d2
d3
, ..., dn
в першу чергу. Створіть список d
з n
елементами.
Читання декількох файлів у список кадрів даних
Це робиться досить легко під час читання у файлах. Можливо, у вас є файли data1.csv, data2.csv, ...
в каталозі. Ваша мета - список кадрів data.frames mydata
. Перше, що вам потрібно - вектор з усіма іменами файлів. Ви можете побудувати це з пастою (наприклад, my_files = paste0("data", 1:5, ".csv")
), але це, ймовірно , простіше у використанні , list.files
щоб захопити всі відповідні файли: my_files <- list.files(pattern = "\\.csv$")
. Ви можете використовувати регулярні вирази для відповідності файлам, детальніше про регулярні вирази читайте в інших питаннях, якщо вам там потрібна допомога. Таким чином, ви можете захопити всі файли CSV, навіть якщо вони не дотримуються приємної схеми іменування. Або ви можете скористатись вигадливішою схемою регулярних виразів, якщо вам потрібно вибрати певні файли CSV з безлічі їх.
На даний момент більшість початківців R використовуватимуть for
цикл, і в цьому немає нічого поганого, він працює просто чудово.
my_data <- list()
for (i in seq_along(my_files)) {
my_data[[i]] <- read.csv(file = my_files[i])
}
Більш R-подібний спосіб зробити це з lapply
, який є ярликом для вищезазначеного
my_data <- lapply(my_files, read.csv)
Звичайно, замініть інші функції імпорту даних на read.csv
необхідні. readr::read_csv
або data.table::fread
буде швидше, або вам може знадобитися інша функція для іншого типу файлів.
У будь-якому випадку зручно називати елементи списку, щоб відповідати файлам
names(my_data) <- gsub("\\.csv$", "", my_files)
# or, if you prefer the consistent syntax of stringr
names(my_data) <- stringr::str_replace(my_files, pattern = ".csv", replacement = "")
Розбиття кадру даних на список кадрів даних
Це дуже просто, базова функція split()
робить це за вас. Ви можете розділити на стовпчик (або стовпці) даних або будь-що інше, що вам потрібно
mt_list = split(mtcars, f = mtcars$cyl)
# This gives a list of three data frames, one for each value of cyl
Це також хороший спосіб розбити кадр даних на частини для перехресної перевірки. Можливо, ви хочете розділити їх mtcars
на навчальні, тестові та перевірочні роботи.
groups = sample(c("train", "test", "validate"),
size = nrow(mtcars), replace = TRUE)
mt_split = split(mtcars, f = groups)
# and mt_split has appropriate names already!
Моделювання списку кадрів даних
Можливо, ви імітуєте дані, приблизно так:
my_sim_data = data.frame(x = rnorm(50), y = rnorm(50))
Але хто робить лише одне моделювання? Ви хочете зробити це 100 разів, 1000 разів, більше! Але вам не потрібно 10 000 кадрів даних у вашій робочій області. Використовуйте replicate
та додайте їх до списку:
sim_list = replicate(n = 10,
expr = {data.frame(x = rnorm(50), y = rnorm(50))},
simplify = F)
Особливо в цьому випадку слід також розглянути, чи справді вам потрібні окремі кадри даних, чи однаково працює також один кадр даних із стовпцем "групи"? Використовувати data.table
або dplyr
досить просто робити речі "за групою" в кадрі даних.
Я не вніс свої дані до списку :( я буду наступного разу, але що я можу зробити зараз?
Якщо вони мають незвичайний асортимент (що незвично), ви можете просто призначити їх:
mylist <- list()
mylist[[1]] <- mtcars
mylist[[2]] <- data.frame(a = rnorm(50), b = runif(50))
...
Якщо у вас є кадри даних з ім'ям у вигляді малюнка, наприклад, df1
, df2
, df3
і ви хочете їх в списку, ви можете get
їх , якщо ви можете написати регулярний вираз для імен. Щось на зразок
df_list = mget(ls(pattern = "df[0-9]"))
# this would match any object with "df" followed by a digit in its name
# you can test what objects will be got by just running the
ls(pattern = "df[0-9]")
# part and adjusting the pattern until it gets the right objects.
Як правило, mget
використовується для отримання декількох об'єктів та повернення їх у названий список. Його аналог get
використовується для отримання одного об’єкта та повернення його (не в списку).
Поєднання списку кадрів даних в єдиний кадр даних
Поширене завдання - поєднання списку кадрів даних в один великий кадр даних. Якщо ви хочете скласти їх один на одного, ви б використали rbind
для пари, але для списку кадрів даних тут є три хороших варіанти:
# base option - slower but not extra dependencies
big_data = do.call(what = rbind, args = df_list)
# data table and dplyr have nice functions for this that
# - are much faster
# - add id columns to identify the source
# - fill in missing values if some data frames have more columns than others
# see their help pages for details
big_data = data.table::rbindlist(df_list)
big_data = dplyr::bind_rows(df_list)
(Аналогічно використовуючи cbind
або dplyr::bind_cols
для стовпців.)
Щоб об'єднати (приєднати) список кадрів даних, ви можете побачити ці відповіді . Часто, ідея полягає в тому , щоб використовувати Reduce
з merge
(або який - або іншою функцією з'єднання) , щоб отримати їх разом.
Навіщо ставити дані в список?
Поміщений аналогічні дані в списках , тому що ви хочете робити подібні речі для кожного кадру даних, а також функції , такі як lapply
, sapply
do.call
, пакет , і старі функції дозволяють легко зробити це. Приклади людей, які легко роблять справи зі списками, є в УС.purrr
plyr
l*ply
Навіть якщо ви використовуєте низький цикл для циклу, набагато простіше перебирати елементи списку, ніж це створювати імена змінних paste
і отримувати доступ до об'єктів get
. Простіше також налагоджувати.
Подумайте про масштабованість . Якщо вам дійсно потрібно тільки три змінні, це добре для використання d1
, d2
, d3
. Але тоді, якщо виявиться, що вам справді потрібно 6, це набагато більше набору тексту. І в наступний раз, коли вам потрібно 10 або 20, ви опиняєтеся копіювання і вставки рядків коди, можливо , з допомогою пошуку / замін для зміни d14
до d15
, і ви думаєте , що це не так, як програмування має бути . Якщо ви використовуєте список, різниця між 3 випадками, 30 випадками та 300 випадками - це максимум один рядок коду --- взагалі не змінюється, якщо кількість випадків автоматично визначається, наприклад, скільки .csv
файлів у вашому каталог.
Ви можете назвати елементи списку, якщо ви хочете використовувати щось, крім числових індексів, для доступу до ваших кадрів даних (і ви можете використовувати обидва, це не вибір XOR).
Загалом, використання списків призведе до того, щоб ви писали чистіший, легший для читання код, що призведе до меншої кількості помилок та меншої плутанини.
=
не<-
всерединіdata.frame()
. Використовуючи<-
ви створюєтеy1
іy2
у вашому глобальному середовищі, і ваш кадр даних - це не те, що ви хочете.