Teraz, gdy mamy już dane potrzebne do pozostałej części przykładu, nauczymy się, jak z nim pracować przy użyciu baz danych. W tej sekcji dowiemy się, jak zapisać nasze dane w relacyjnej bazie danych, a także jak je odczytać. Nie będziemy zagłębiać się w zaawansowane operacje lub przepływy pracy. Przyjrzymy się tylko podstawom i tę sekcję można pominąć, jeśli nie jesteś zainteresowany tym tematem. Znajomość tego nie jest krytyczna, aby odtworzyć resztę RMySQL. Istnieją różne pakiety do pracy z bazami danych i działają one prawie tak samo. Wybraliśmy pakiet RMySQL, ponieważ jest przeznaczony dla bazy danych MySQL, która jest bardzo popularna i łatwa w obsłudze w prawie wszystkich systemach operacyjnych. Aby móc odtworzyć ten kod, będziesz potrzebować poprawnie skonfigurowanej bazy danych MySQL na swoim komputerze i nie będziemy tutaj omawiać szczegółów, jak to zrobić. W Internecie można znaleźć wiele dobrych zasobów. Od tego momentu zakładamy, że masz gotową bazę danych:
install.packages(„RMySQL”)
Pierwszą rzeczą, którą musimy zrobić, aby pracować z bazami danych, jest łączenie się i odłączanie od nich. Aby to zrobić, używamy funkcji dbConnect() i dbDisconnect. Funkcja dbConnect zwraca obiekt, który zawiera połączenie z bazą danych, i które należy zastosować we wszystkich kolejnych działaniach dotyczących bazy danych. Nazwiemy ten obiekt db, aby przypomnieć nam, że reprezentuje bazę danych, z którą pracujemy:
db <- dbConnect(MySQL () , user = <YOUR_USER>, paswword = <YOUR_PASSWORD>, host = „localhost”)
dbDisconnect(db)
#> [1] TRUE
Jeśli używasz bazy danych, która nie działa na tym samym komputerze, z którego korzystasz z języka R, możesz użyć odpowiedniego adresu IP w parametrach host, tak jak w przypadku każdego zdalnego połączenia SQL. Jest piąty parametr, którego musimy użyć, gdy znamy nazwę bazy danych, z którą się łączymy (pojedynczy serwer MySQL może mieć w sobie wiele baz danych). Gdy zobaczysz wartość TRUE po próbie odłączenia się od bazy danych, oznacza to, że wszystko zostało wykonane poprawnie. Aby wysłać zapytanie do serwera bazy danych, używamy funkcji dbSendQuery() po ponownym połączeniu się z nim. Tworzymy nową bazę danych sales (która będzie zawierała nasze tabele sales, and i client_messages) w naszym MySQL serwer poprzez wykonanie:
dbSendQuery(db, „DROP DATABASE IF EXIST sales;”)
dbSendQuery(db, „CREATE DATABASE sales;”)
Ponieważ składnia MySQL wymaga „;” na końcu każdego zapytania, w zależności od konfiguracji, możesz otrzymać błąd, jeśli ich nie wstawisz. Teraz rozłączymy się i ponownie połączymy z serwerem, ale tym razem określimy z jaką konkretną bazą danych chcemy pracować (baza danych sales, którą właśnie stworzyliśmy):
dbDisconnect(db)
db <- dbConnect(
MySQL(),
user = <YOUR_USER>,
password = <YOUR_PASSWORD>,
host = „localhost”,
dbame = „sales”
)
Teraz zapiszemy dane, które zasymulowaliśmy na serwerze MySQL. Aby to zrobić, używamy funkcji dbWriteTable(). Pierwszy argument to obiekt połączenia z bazą danych, drugi argument to nazwa tabeli, w której chcemy przechowywać dane, trzeci argument to ramka danych, która zawiera dane, które chcemy przechowywać, a czwarty argument to nazwa sugeruje, nadpisze (zamiast dołączać) wszelkie dane już obecne w bazie danych. Aby wczytać pełną tabelę z serwera MySQL do R, używamy funkcji dbReadTable(). Należy jednak pamiętać, że kiedy to robimy, wszelkie informacje dotyczące czynników są tracone, a ramka danych wie, że zawiera tylko ciągi znaków, co jest sposobem przechowywania danych na serwerze MySQL. Aby to sprawdzić, możesz przyjrzeć się strukturze danych odczytywanych z serwera MySQL za pomocą funkcji str(). Nie pokażemy tutaj danych wyjściowych, aby zaoszczędzić miejsce, ale przekonasz się, że sales zawiera informacje o czynniku, podczas gdy sales_from_db nie:
sales_from_db <- dbReadTable(db,”sales”)
str(sales)
str(sales_from_db)
Brak rozwiązania problemu z metadanymi dotyczącymi zmiennych czynnikowych będzie miał konsekwencje, gdy utworzymy nasze wizualizacje w następnym rozdziale. Możemy sobie z tym poradzić teraz lub później, ale ponieważ ta część dotyczy pracy z danymi, tutaj pokażemy, jak to zrobić. Najpierw utworzymy funkcję read_table(), która będzie opakowywać funkcję dbReadTable(). Ta funkcja read_table() sprawdzi, która tabela jest odczytywana i zastosuje odpowiednie metadane, wywołując add_sales_metadata(), add_clients_metadata lub add_client_messages_metadata. Zwróć uwagę, że jeśli odczytywana tabela nie jest jedną z tych trzech, nie będziemy na razie wiedzieć, jakie metadane dodać, więc po prostu zwrócimy tabelę bezpośrednio:
read_table <- function(db,table) {
data <- dbReadTable(db, table)
if (table = = „sales”) {
return(add_sales_metadata(data))
} else if (table == „clients’) {
return(add_clients_metadata(data))
} else if (table = = „client_messages”) {
return(add_client_messages_metadata(data))
} else {
return(data)
}
}
Sposób, w jaki dodajemy metadane do każdego przypadku, polega na ponownym zdefiniowaniu zmiennych czynników, tak jak robiliśmy to wcześniej, a także na przekształceniu obiektów daty, które są również odbierane jako ciągi. Nie musimy nic więcej zmieniać w danych:
add_sales_metadata <- function(data) {
status_levels <- c(„PENDING”, „DELIVERED”, RETURNED”, „CANCLLED”)
protein_source_levels <- c(„BEEF”, „FISH”, „CHICKEN”, „VEGETARIAN”)
continent_levels <- c(„AMERICA”, „EUROPE”, „ASIA”)
delivery_levels <- c(„IN STORE” , „TO LOCATION”)
paid_levels <- c(„YES”, „NO”)
data$DATE <- as.Date(data$DATE)
data$PROTEIN_SOURCE <-
factor(data$PROTEIN_SOURCE, levels = protein_source-levels)
data$CONTINENT <- fator(data$CONTINENT, levels = continent_levels)
data$DELIVERY <- fator(data$DELIVERY, levels = delivery_levels)
data$STATUS <- fator(data$STATUS , levels = status_levels)
data$PAID <- fator(data$PAID, levels = paid_levels)
return(data)
}
add_clients_metadata <-fuction(data) {
gender_levels <- c(„FEMALE”, „MALE”)
star_levels <- c(„1”, „2”, „3”, „4”, „5”)
data$BIRTH_DATE <- as.Date(data$BIRTH_DATE)
data$CLIENT_SINCE <- as.Date(data$CLIENT_SINCE)
data$GENDER <- factor(data$GENDER, levels = gender_levels)
data$STARS <- factor(data$STARS, levels = star_levels)
return(data)
}
add_client_messages_metadata <- function(data) {
star_levels <- c(„1”, „2”, „3”, „4”, „5”)
data$DATE <- as.Date(Data$DATE)
data$STARS <- factor(data$STARS, levels = star_levels)
return(data)
}
Teraz widzimy, że zarówno sales, jak i sales_from zawierają te same metadane. Ponownie nie pokazujemy danych wyjściowych, aby zaoszczędzić miejsce, ale zobaczysz, że metadane współczynnika są teraz zachowywane podczas odczytu z serwera MySQL:
sales_from_db <- read_table(db, „sales”)
str(sales)
str(sales_from_db)
Ponieważ mają te same dane i metadane, teraz można bezpiecznie odczytać dane z serwera MySQL, gdy zajdzie taka potrzeba. Pamiętaj tylko, aby używać funkcji read_table zamiast funkcji dbReadTable.
Odczytywanie pełnych tabel z serwera MySQL za pomocą dbReadTable jest praktyczne tylko wtedy, gdy tablice nie są zbyt duże. Jeśli pracujesz z bazą danych w rzeczywistym problemie, prawdopodobnie tak nie jest. Jeśli dane, które próbujesz odczytać, są zbyt duże, użyj kombinacji funkcji dbSendQuery i fetch().
Jeśli chcesz wiedzieć, jaki typ danych będzie używany na serwerze MySQL do przechowywania wysyłanych danych, możesz użyć funkcji dbDataType z argumentem MySQL(), a także typ danych, którego typu serwera chcesz się dowiedzieć:
dbDataType(MySQL (), „a”)
#> [1] “text”
dbDataType(MySQL (), 1.5)
#> [1] “double”
Na koniec możesz użyć funkcji dbListTables() i dbListFields(), aby znaleźć tabele dostępne w bazie danych i pola dostępne dla odpowiednio konkretną tabelę. Jeśli postępowałeś według tego przykładu do tej pory, powinieneś zobaczyć:
dbListTables(db)
#> [1] “client_messages” “clients” “sales”
dbListFields(db, „sales”)
#> [1] “row_names” “SALE_ID” “CLIENT_ID” “DATE”
#> [5] “QUANTITY” “COST” “PRICE” “DISCOUNT”
#> [9] “PROTEIN” “CARBS” “FAT” “PROTEIN_SOURCE”
#> [13] “STORE” “DELIVERY” “STATUS” “PAID”
dbListFields(db, „clients”)
#> [1] “row_names” “CLIENT_ID” “BIRTH_DATE” “CLIENT_SINCE”
“GENDER”
#> [6] “STARS”
dbListFields(db, „client_messages”)
#> [1] “row_names” “SALE_ID” “DATE” “STARS” “SUMMARY”
“MESSAGE”
Zwróć uwagę, że widzisz pole row.names, ponieważ jest ono niezbędne dla funkcjonalności MySQL, ale kiedy faktycznie odczytujesz dane z bazy danych, nie otrzymasz tego pola. Otrzymasz wszystkie inne pokazane pola (te napisane wielkimi literami).