Pozostałe odpowiedzi pokazać wam jak zrobić listę data.frames kiedy już kilka data.frames, np d1, d2.... Mając nazwanych kolejno ramek danych jest problemem, a umieszczenie ich w wykazie jest to dobra poprawka, ale najlepszą praktyką jest unikanie posiadania wiązki danych. ramek nie ma na liście .
Inne odpowiedzi podają wiele szczegółów na temat przypisywania ramek danych elementom listy, uzyskiwania do nich dostępu itp. Omówimy to trochę tutaj, ale głównym punktem jest to, że nie czekaj, aż będziesz miał sporo data.framesaby dodać je do listy. Zacznij od listy.
Pozostała część tej odpowiedzi obejmie niektóre typowe przypadki, w których możesz ulec pokusie, aby utworzyć sekwencyjne zmienne i pokazać, jak przejść bezpośrednio do list. Jeśli dopiero zaczynasz korzystać z list w R, możesz także przeczytać Jaka jest różnica między dostępem do elementów listy [[a [dostępem do nich? .
Listy od początku
Nigdy nie twórz d1 d2 d3... ... dnw pierwszej kolejności. Utwórz listę dz nelementami.
Odczytywanie wielu plików do listy ramek danych
Odbywa się to dość łatwo podczas wczytywania plików. Może masz pliki data1.csv, data2.csv, ...w katalogu. Twoim celem jest lista nazwanych data.frames mydata. Pierwszą rzeczą, której potrzebujesz, jest wektor ze wszystkimi nazwami plików. Można skonstruować ten pastą (np my_files = paste0("data", 1:5, ".csv")), ale to chyba łatwiejsze w użyciu list.files, aby pobrać wszystkie odpowiednie pliki: my_files <- list.files(pattern = "\\.csv$"). Możesz użyć wyrażeń regularnych, aby dopasować pliki, przeczytaj więcej o wyrażeniach regularnych w innych pytaniach, jeśli potrzebujesz pomocy. W ten sposób możesz pobrać wszystkie pliki CSV, nawet jeśli nie są zgodne z dobrym schematem nazewnictwa. Lub możesz użyć bardziej wyszukanego wzorca wyrażenia regularnego, jeśli chcesz wybrać niektóre pliki CSV z kilku z nich.
W tym momencie większość początkujących R używa forpętli i nie ma w tym nic złego, działa dobrze.
my_data <- list()
for (i in seq_along(my_files)) {
my_data[[i]] <- read.csv(file = my_files[i])
}
Bardziej podobny do R sposób to zrobić lapply, co jest skrótem do powyższego
my_data <- lapply(my_files, read.csv)
Oczywiście zastąp odpowiednio inną funkcję importu danych read.csv. readr::read_csvlub data.table::freadbędzie szybszy, lub możesz potrzebować innej funkcji dla innego typu pliku.
Tak czy inaczej, warto nazwać elementy listy, aby pasowały do plików
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 = "")
Dzielenie ramki danych na listę ramek danych
Jest to bardzo łatwe, funkcja podstawowa split()robi to za Ciebie. Możesz dzielić według kolumny (lub kolumn) danych lub według dowolnej innej opcji
mt_list = split(mtcars, f = mtcars$cyl)
# This gives a list of three data frames, one for each value of cyl
Jest to również dobry sposób na rozbicie ramki danych na części w celu weryfikacji krzyżowej. Może chcesz podzielić się mtcarsna części szkoleniowe, testowe i weryfikacyjne.
groups = sample(c("train", "test", "validate"),
size = nrow(mtcars), replace = TRUE)
mt_split = split(mtcars, f = groups)
# and mt_split has appropriate names already!
Symulowanie listy ramek danych
Może symulujesz dane, coś takiego:
my_sim_data = data.frame(x = rnorm(50), y = rnorm(50))
Ale kto wykonuje tylko jedną symulację? Chcesz to zrobić 100 razy, 1000 razy, więcej! Ale nie chcesz 10 000 ramek danych w swoim obszarze roboczym. Użyj replicatei umieść je na liście:
sim_list = replicate(n = 10,
expr = {data.frame(x = rnorm(50), y = rnorm(50))},
simplify = F)
W tym przypadku szczególnie powinieneś rozważyć, czy naprawdę potrzebujesz osobnych ramek danych, czy też pojedyncza ramka danych z kolumną „grupową” równie dobrze by działała? Używanie data.tablelub dplyrdość łatwo jest robić rzeczy „grupowo” w ramce danych.
Nie umieściłem moich danych na liście :( Będę następnym razem, ale co mogę teraz zrobić?
Jeśli są dziwnym asortymentem (co jest niezwykłe), możesz po prostu przypisać im:
mylist <- list()
mylist[[1]] <- mtcars
mylist[[2]] <- data.frame(a = rnorm(50), b = runif(50))
...
Jeśli masz ramek danych nazwanych we wzór, na przykład df1, df2, df3, i chcesz je na liście, można getje, jeśli możesz napisać wyrażenie regularne pasujące nazwy. Coś jak
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.
Zasadniczo mgetsłuży do pobierania wielu obiektów i zwracania ich na nazwaną listę. Jego odpowiednik getsłuży do pobrania pojedynczego obiektu i zwrócenia go (nie na liście).
Łączenie listy ramek danych w jedną ramkę danych
Częstym zadaniem jest łączenie listy ramek danych w jedną dużą ramkę danych. Jeśli chcesz je ułożyć jeden na drugim, użyj ich rbinddla pary, ale dla listy ramek danych są trzy dobre opcje:
# 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)
(Podobnie przy użyciu cbindlub dplyr::bind_colsdla kolumn.)
Aby scalić (dołączyć) listę ramek danych, możesz zobaczyć te odpowiedzi . Często chodzi o to, aby korzystać Reducez merge(lub innej funkcji łączącej), aby je ze sobą.
Po co umieszczać dane na liście?
Umieścić podobne dane w listach, bo chcesz robić podobne rzeczy do każdej ramki danych, a funkcje takie jak lapply, sapply do.call, opakowanie , a stare funkcje sprawiają, że łatwo to zrobić. Przykłady osób, które łatwo robią rzeczy z listami, są na SO.purrrplyr l*ply
Nawet jeśli używasz mało używanej pętli for, o wiele łatwiej jest zapętlać elementy listy niż konstruować nazwy zmiennych pastei uzyskiwać do nich dostęp get. Łatwiej też debugować.
Pomyśl o skalowalności . Jeśli naprawdę potrzebujesz tylko trzy zmienne, w porządku do użytku d1, d2, d3. Ale jeśli okaże się, że naprawdę potrzebujesz 6, to dużo więcej pisania. Następnym razem, gdy będziesz potrzebować 10 lub 20, przekonasz się, że kopiujesz i wklejasz linie kodu, być może używasz funkcji znajdź / zamień, aby zmienić d14na d15, i myślisz, że nie tak powinno być programowanie . Jeśli używasz listy, różnica między 3 przypadkami, 30 przypadkami i 300 przypadkami wynosi co najwyżej jeden wiersz kodu --- bez zmian, jeśli liczba spraw jest automatycznie wykrywana np. Przez liczbę .csvplików w twoim informator.
Możesz nazwać elementy listy, na wypadek gdybyś chciał użyć czegoś innego niż indeksy numeryczne, aby uzyskać dostęp do swoich ramek danych (i możesz użyć obu, nie jest to wybór XOR).
Ogólnie rzecz biorąc, używanie list doprowadzi Cię do napisania czystszego, łatwiejszego do odczytania kodu, co spowoduje mniej błędów i mniej zamieszania.
=nie używaj w<-środkudata.frame(). Używając<-tworzeniay1iy2w swoim globalnym środowisku, twoja ramka danych nie jest taka, jak chcesz.