R Language
Ramki danych
Szukaj…
Składnia
data.frame (..., row.names = NULL, check.rows = FALSE, check.names = TRUE, stringsAsFactors = default.stringsAsFactors ())
as.data.frame (x, row.names = NULL, opcjonalnie = FALSE, ...) # funkcja ogólna
as.data.frame (x, ..., stringsAsFactors = default.stringsAsFactors ()) # Metoda S3 dla klasy „znak”
as.data.frame (x, row.names = NULL, opcjonalnie = FALSE, ..., stringsAsFactors = default.stringsAsFactors ()) # Metoda S3 dla klasy „macierz”
is.data.frame (x)
Utwórz pustą ramkę danych
Data.frame to specjalny rodzaj listy: jest prostokątny . Każdy element (kolumna) listy ma tę samą długość, a każdy wiersz ma „nazwę wiersza”. Każda kolumna ma swoją klasę, ale klasa jednej kolumny może różnić się od klasy innej kolumny (w przeciwieństwie do macierzy, w której wszystkie elementy muszą mieć tę samą klasę).
Zasadniczo data.frame nie może mieć wierszy ani kolumn:
> structure(list(character()), class = "data.frame")
NULL
<0 rows> (or 0-length row.names)
Ale to niezwykłe. Bardziej typowe jest to, że data.frame ma wiele kolumn i wiele wierszy. Oto ramka danych z trzema wierszami i dwiema kolumnami ( a
to klasa numeryczna, a b
to klasa znakowa):
> structure(list(a = 1:3, b = letters[1:3]), class = "data.frame")
[1] a b
<0 rows> (or 0-length row.names)
Aby data.frame mogła zostać wydrukowana, będziemy musieli podać niektóre nazwy wierszy. Tutaj używamy tylko liczb 1: 3:
> structure(list(a = 1:3, b = letters[1:3]), class = "data.frame", row.names = 1:3)
a b
1 1 a
2 2 b
3 3 c
Teraz staje się oczywiste, że mamy ramkę data.frame z 3 wierszami i 2 kolumnami. Możesz to sprawdzić za pomocą nrow()
, ncol()
i dim()
:
> x <- structure(list(a = numeric(3), b = character(3)), class = "data.frame", row.names = 1:3)
> nrow(x)
[1] 3
> ncol(x)
[1] 2
> dim(x)
[1] 3 2
R udostępnia dwie inne funkcje (oprócz structure()
), których można użyć do utworzenia ramki danych. Pierwszy nazywa się intuicyjnie data.frame()
. Sprawdza, czy podane nazwy kolumn są prawidłowe, czy elementy listy mają tę samą długość, i podaje niektóre automatycznie generowane nazwy wierszy. Oznacza to, że dane wyjściowe data.frame()
mogą teraz zawsze mieć dokładnie to, czego oczekujesz:
> str(data.frame("a a a" = numeric(3), "b-b-b" = character(3)))
'data.frame': 3 obs. of 2 variables:
$ a.a.a: num 0 0 0
$ b.b.b: Factor w/ 1 level "": 1 1 1
Druga funkcja nazywa się as.data.frame()
. Można tego użyć, aby zmusić obiekt, który nie jest data.frame, do bycia data.frame, uruchamiając go przez data.frame()
. Jako przykład rozważmy macierz:
> m <- matrix(letters[1:9], nrow = 3)
> m
[,1] [,2] [,3]
[1,] "a" "d" "g"
[2,] "b" "e" "h"
[3,] "c" "f" "i"
A wynik:
> as.data.frame(m)
V1 V2 V3
1 a d g
2 b e h
3 c f i
> str(as.data.frame(m))
'data.frame': 3 obs. of 3 variables:
$ V1: Factor w/ 3 levels "a","b","c": 1 2 3
$ V2: Factor w/ 3 levels "d","e","f": 1 2 3
$ V3: Factor w/ 3 levels "g","h","i": 1 2 3
Podzbiór wierszy i kolumn z ramki danych
Składnia dostępu do wierszy i kolumn: [
, [[
i $
W tym temacie omówiono najczęstszą składnię umożliwiającą dostęp do określonych wierszy i kolumn ramki danych. To są
- Jak
matrix
zdata[rows, columns]
z pojedynczymi nawiasamidata[rows, columns]
- Korzystanie z numerów wierszy i kolumn
- Używanie nazw kolumn (i wierszy)
- Jak
list
:- Dane z pojedynczymi nawiasami
data[columns]
aby uzyskać ramkę danych - Z
data[[one_column]]
podwójnych nawiasachdata[[one_column]]
aby uzyskać wektor
- Dane z pojedynczymi nawiasami
- Z
$
za dane z jednej kolumnydata$column_name
mtcars
to wbudowaną mtcars
danych mtcars
.
Jak macierz: data[rows, columns]
Z indeksami numerycznymi
Korzystając z wbudowanych ramek mtcars
, możemy wyodrębnić wiersze i kolumny za pomocą nawiasów []
z przecinkiem. Wskaźniki przed przecinkiem są wierszami:
# get the first row
mtcars[1, ]
# get the first five rows
mtcars[1:5, ]
Podobnie po przecinku są kolumny:
# get the first column
mtcars[, 1]
# get the first, third and fifth columns:
mtcars[, c(1, 3, 5)]
Jak pokazano powyżej, jeśli wiersze lub kolumny pozostaną puste, wszystkie zostaną wybrane. mtcars[1, ]
wskazuje pierwszy wiersz ze wszystkimi kolumnami.
Z nazwami kolumn (i wierszy)
Jak dotąd jest to identyczne z dostępem do wierszy i kolumn macierzy. W przypadku data.frame
s przez większość czasu lepiej jest używać nazwy kolumny niż indeksu kolumny. Odbywa się to za pomocą character
o nazwie kolumny zamiast numeric
z numerem kolumny:
# get the mpg column
mtcars[, "mpg"]
# get the mpg, cyl, and disp columns
mtcars[, c("mpg", "cyl", "disp")]
Chociaż rzadziej są używane, nazwy wierszy mogą być również używane:
mtcars["Mazda Rx4", ]
Rzędy i kolumny razem
Argumentów wiersza i kolumny można używać razem:
# first four rows of the mpg column
mtcars[1:4, "mpg"]
# 2nd and 5th row of the mpg, cyl, and disp columns
mtcars[c(2, 5), c("mpg", "cyl", "disp")]
Ostrzeżenie o wymiarach:
Podczas korzystania z tych metod wyodrębnienie wielu kolumn spowoduje odzyskanie ramki danych. Jeśli jednak wyodrębnisz pojedynczą kolumnę, otrzymasz domyślny wektor, a nie ramkę danych.
## multiple columns returns a data frame
class(mtcars[, c("mpg", "cyl")])
# [1] "data.frame"
## single column returns a vector
class(mtcars[, "mpg"])
# [1] "numeric"
Są na to dwa sposoby. Jednym z nich jest traktowanie ramki danych jako listy (patrz poniżej), drugim jest dodanie argumentu drop = FALSE
. To mówi R, aby nie „upuszczał nieużywanych wymiarów”:
class(mtcars[, "mpg", drop = FALSE])
# [1] "data.frame"
Zauważ, że macierze działają w ten sam sposób - domyślnie pojedyncza kolumna lub wiersz będzie wektorem, ale jeśli podasz drop = FALSE
, możesz zachować go jako macierz z jedną kolumną lub z jednym wierszem.
Jak lista
Ramki danych są zasadniczo list
s, tzn. Są listą wektorów kolumn (wszystkie muszą mieć tę samą długość). Listy można podzielić na pojedyncze nawiasy kwadratowe [
dla podlisty lub podwójne nawiasy kwadratowe [[
dla pojedynczego elementu.
Z data[columns]
pojedynczych nawiasach data[columns]
Gdy użyjesz pojedynczych nawiasów i bez przecinków, otrzymasz kolumnę z powrotem, ponieważ ramki danych są listami kolumn.
mtcars["mpg"]
mtcars[c("mpg", "cyl", "disp")]
my_columns <- c("mpg", "cyl", "hp")
mtcars[my_columns]
Pojedyncze nawiasy kwadratowe jak lista vs. pojedyncze nawiasy kwadratowe Różnica między data[columns]
a data[, columns]
polega na tym, że podczas traktowania data.frame
jako list
(bez przecinków w nawiasach data.frame
) zwracanym obiektem będzie data.frame
. Jeśli użyjesz przecinka do traktowania data.frame
jak matrix
wówczas wybranie jednej kolumny zwróci wektor, ale wybranie wielu kolumn zwróci data.frame
.
## When selecting a single column
## like a list will return a data frame
class(mtcars["mpg"])
# [1] "data.frame"
## like a matrix will return a vector
class(mtcars[, "mpg"])
# [1] "numeric"
Z data[[one_column]]
podwójnych nawiasach data[[one_column]]
Aby wyodrębnić pojedynczą kolumnę jako wektor , traktując data.frame
jako list
, możesz użyć podwójnych nawiasów data.frame
[[
. Będzie to działać tylko dla jednej kolumny na raz.
# extract a single column by name as a vector
mtcars[["mpg"]]
# extract a single column by name as a data frame (as above)
mtcars["mpg"]
Używanie $
aby uzyskać dostęp do kolumn
Pojedynczą kolumnę można wyodrębnić za pomocą magicznego skrótu $
bez użycia cytowanej nazwy kolumny:
# get the column "mpg"
mtcars$mpg
Kolumny dostępne za pomocą $
zawsze będą wektorami, a nie ramkami danych.
Wady $
za dostęp do kolumn
$
Może być wygodnym skrótem, szczególnie jeśli pracujesz w środowisku (takim jak RStudio), które w tym przypadku automatycznie uzupełni nazwę kolumny. Jednak $
ma również wady: używa niestandardowej oceny, aby uniknąć potrzeby cudzysłowów, co oznacza, że nie będzie działać, jeśli nazwa kolumny jest przechowywana w zmiennej.
my_column <- "mpg"
# the below will not work
mtcars$my_column
# but these will work
mtcars[, my_column] # vector
mtcars[my_column] # one-column data frame
mtcars[[my_column]] # vector
Ze względu na te obawy najlepiej zastosować $
w interaktywnych sesjach R, gdy nazwy kolumn są stałe. Do użytku programowego , na przykład podczas pisania funkcji uogólnionej, która będzie używana w różnych zestawach danych o różnych nazwach kolumn, należy unikać $
.
Zauważ też, że domyślnym zachowaniem jest stosowanie częściowego dopasowania tylko podczas wyodrębniania z obiektów rekurencyjnych (z wyjątkiem środowisk) o $
# give you the values of "mpg" column
# as "mtcars" has only one column having name starting with "m"
mtcars$m
# will give you "NULL"
# as "mtcars" has more than one columns having name starting with "d"
mtcars$d
Zaawansowane indeksowanie: indeksy ujemne i logiczne
Ilekroć mamy opcję użycia liczb dla indeksu, możemy również użyć liczb ujemnych, aby pominąć niektóre indeksy lub wektor boolowski (logiczny), aby wskazać dokładnie, które elementy należy zachować.
Wskaźniki ujemne pomijają elementy
mtcars[1, ] # first row
mtcars[ -1, ] # everything but the first row
mtcars[-(1:10), ] # everything except the first 10 rows
Wektory logiczne wskazują określone elementy, które należy zachować
Możemy użyć warunku takiego jak <
aby wygenerować wektor logiczny i wyodrębnić tylko wiersze spełniające warunek:
# logical vector indicating TRUE when a row has mpg less than 15
# FALSE when a row has mpg >= 15
test <- mtcars$mpg < 15
# extract these rows from the data frame
mtcars[test, ]
Możemy również ominąć krok zapisywania zmiennej pośredniej
# extract all columns for rows where the value of cyl is 4.
mtcars[mtcars$cyl == 4, ]
# extract the cyl, mpg, and hp columns where the value of cyl is 4
mtcars[mtcars$cyl == 4, c("cyl", "mpg", "hp")]
Funkcje ułatwiające manipulowanie data.frames
Niektóre funkcje data.frames
manipulowanie data.frames
to subset()
, transform()
, with()
i data.frames
within()
.
podzbiór
Funkcja subset()
pozwala na podzestawienie data.frame
w wygodniejszy sposób (podzbiór działa również z innymi klasami):
subset(mtcars, subset = cyl == 6, select = c("mpg", "hp"))
mpg hp
Mazda RX4 21.0 110
Mazda RX4 Wag 21.0 110
Hornet 4 Drive 21.4 110
Valiant 18.1 105
Merc 280 19.2 123
Merc 280C 17.8 123
Ferrari Dino 19.7 175
W powyższym kodzie pytamy tylko o linie, w których cyl == 6
oraz o kolumny mpg
i hp
. Ten sam wynik można osiągnąć za pomocą []
z następującym kodem:
mtcars[mtcars$cyl == 6, c("mpg", "hp")]
przekształcać
Funkcja transform()
jest funkcją wygodną do zmiany kolumn wewnątrz data.frame
. Na przykład poniższy kod dodaje kolejną kolumnę o nazwie mpg2
z wynikiem mpg^2
do mtcars
data.frame
:
mtcars <- transform(mtcars, mpg2 = mpg^2)
z i wewnątrz
Zarówno za with()
i data.frame
within()
pozwala oceniać wyrażenia w środowisku data.frame
, pozwalając na nieco czystszą składnię, oszczędzając ci użycia $
lub []
.
Na przykład, jeśli chcesz utworzyć, zmienić i / lub usunąć wiele kolumn w airquality
data.frame
:
aq <- within(airquality, {
lOzone <- log(Ozone) # creates new column
Month <- factor(month.abb[Month]) # changes Month Column
cTemp <- round((Temp - 32) * 5/9, 1) # creates new column
S.cT <- Solar.R / cTemp # creates new column
rm(Day, Temp) # removes columns
})
Wprowadzenie
Ramy danych są prawdopodobnie strukturą danych, której będziesz najczęściej używać w swoich analizach. Ramka danych jest specjalnym rodzajem listy, która przechowuje wektory tej samej długości różnych klas. Ramki danych tworzy się za pomocą funkcji data.frame
. Poniższy przykład pokazuje to, łącząc wektor numeryczny i znakowy w ramkę danych. Wykorzystuje on :
operatora, który będzie tworzyć wektor zawierający wszystkie liczby całkowite od 1 do 3.
df1 <- data.frame(x = 1:3, y = c("a", "b", "c"))
df1
## x y
## 1 1 a
## 2 2 b
## 3 3 c
class(df1)
## [1] "data.frame"
Obiekty ramek danych nie są drukowane ze znakami cudzysłowu, więc klasa kolumn nie zawsze jest oczywista.
df2 <- data.frame(x = c("1", "2", "3"), y = c("a", "b", "c"))
df2
## x y
## 1 1 a
## 2 2 b
## 3 3 c
Bez dalszego badania nie można rozróżnić kolumn „x” w df1
i df2
. Funkcja str
może być używana do opisywania obiektów bardziej szczegółowo niż klasa.
str(df1)
## 'data.frame': 3 obs. of 2 variables:
## $ x: int 1 2 3
## $ y: Factor w/ 3 levels "a","b","c": 1 2 3
str(df2)
## 'data.frame': 3 obs. of 2 variables:
## $ x: Factor w/ 3 levels "1","2","3": 1 2 3
## $ y: Factor w/ 3 levels "a","b","c": 1 2 3
Tutaj widzisz, że df1
jest data.frame
i ma 3 obserwacje 2 zmiennych, „x” i „y”. Następnie powiedziano ci, że „x” ma liczbę całkowitą typu danych (nieistotne dla tej klasy, ale dla naszych celów zachowuje się jak liczba), a „y” jest czynnikiem z trzema poziomami (kolejna klasa danych, o której nie dyskutujemy). Należy zauważyć, że domyślnie ramki danych przymuszają znaki do czynników. Domyślne zachowanie można zmienić za pomocą parametru stringsAsFactors
:
df3 <- data.frame(x = 1:3, y = c("a", "b", "c"), stringsAsFactors = FALSE)
str(df3)
## 'data.frame': 3 obs. of 2 variables:
## $ x: int 1 2 3
## $ y: chr "a" "b" "c"
Teraz kolumna „y” jest znakiem. Jak wspomniano powyżej, każda „kolumna” ramki danych musi mieć tę samą długość. Próba utworzenia ramki danych z wektorów o różnych długościach spowoduje błąd. (Spróbuj uruchomić data.frame(x = 1:3, y = 1:4)
aby zobaczyć wynikowy błąd.)
Jako przypadki testowe dla ramek danych niektóre dane są domyślnie dostarczane przez R. Jednym z nich jest tęczówka, ładowana w następujący sposób:
mydataframe <- iris
str(mydataframe)
Konwertuj dane przechowywane na liście na pojedynczą ramkę danych za pomocą do.call
Jeśli masz dane zapisane na liście i chcesz przekonwertować tę listę na ramkę danych, funkcja do.call
jest łatwym sposobem na osiągnięcie tego. Ważne jest jednak, aby wszystkie elementy listy miały tę samą długość, aby zapobiec niezamierzonemu recyklingowi wartości.
dataList <- list(1:3,4:6,7:9)
dataList
# [[1]]
# [1] 1 2 3
#
# [[2]]
# [1] 4 5 6
#
# [[3]]
# [1] 7 8 9
dataframe <- data.frame(do.call(rbind, dataList))
dataframe
# X1 X2 X3
# 1 1 2 3
# 2 4 5 6
# 3 7 8 9
Działa również, jeśli twoja lista składa się z samych ramek danych.
dataframeList <- list(data.frame(a = 1:2, b = 1:2, c = 1:2),
data.frame(a = 3:4, b = 3:4, c = 3:4))
dataframeList
# [[1]]
# a b c
# 1 1 1 1
# 2 2 2 2
# [[2]]
# a b c
# 1 3 3 3
# 2 4 4 4
dataframe <- do.call(rbind, dataframeList)
dataframe
# a b c
# 1 1 1 1
# 2 2 2 2
# 3 3 3 3
# 4 4 4 4
Konwertuj wszystkie kolumny data.frame na klasę znaków
Częstym zadaniem jest konwersja wszystkich kolumn data.frame na klasę znaków w celu ułatwienia manipulacji, na przykład w przypadku wysyłania data.frame do RDBMS lub scalania data.frame zawierających czynniki, w których poziomy mogą się różnić między danymi wejściowymi. Frame .
Najlepszym momentem na to jest, gdy dane są wczytywane - prawie wszystkie metody wprowadzania danych, które tworzą ramki danych, mają opcje stringsAsFactors
które można ustawić na FALSE
.
Jeśli dane zostały już utworzone, kolumny czynników można przekonwertować na kolumny znaków, jak pokazano poniżej.
bob <- data.frame(jobs = c("scientist", "analyst"),
pay = c(160000, 100000), age = c(30, 25))
str(bob)
'data.frame': 2 obs. of 3 variables: $ jobs: Factor w/ 2 levels "analyst","scientist": 2 1 $ pay : num 160000 100000 $ age : num 30 25
# Convert *all columns* to character
bob[] <- lapply(bob, as.character)
str(bob)
'data.frame': 2 obs. of 3 variables: $ jobs: chr "scientist" "analyst" $ pay : chr "160000" "1e+05" $ age : chr "30" "25"
# Convert only factor columns to character
bob[] <- lapply(bob, function(x) {
if is.factor(x) x <- as.character(x)
return(x)
})
Podzbiór wierszy według wartości kolumny
Wbudowane funkcje mogą dzielić rows
columns
spełniające warunki.
df <- data.frame(item = c(1:10),
price_Elasticity = c(-0.57667, 0.03205, -0.04904, 0.10342, 0.04029,
0.0742, 0.1669, 0.0313, 0.22204, 0.06158),
total_Margin = c(-145062, 98671, 20576, -56382, 207623, 43463, 1235,
34521, 146553, -74516))
Aby znaleźć rows
z price_Elasticity > 0
:
df[df$price_Elasticity > 0, ]
item price_Elasticity total_Margin
2 2 0.03205 98671
4 4 0.10342 -56382
5 5 0.04029 207623
6 6 0.07420 43463
7 7 0.16690 1235
8 8 0.03130 34521
9 9 0.22204 146553
10 10 0.06158 -74516
podzbiór oparty na price_Elasticity > 0
i total_Margin > 0
:
df[df$price_Elasticity > 0 & df$total_Margin > 0, ]
item price_Elasticity total_Margin
2 2 0.03205 98671
5 5 0.04029 207623
6 6 0.07420 43463
7 7 0.16690 1235
8 8 0.03130 34521
9 9 0.22204 146553