Udostępnij za pośrednictwem


Praca z ramkami danych i tabelami w języku R

W tym artykule opisano sposób używania pakietów języka R, takich jak SparkR, sparklyr i dplyr do pracy z tabelami R data.frames, Spark DataFrames i in-memory.

Pamiętaj, że podczas pracy z usługą SparkR, sparklyr i dplyr możesz stwierdzić, że możesz ukończyć określoną operację ze wszystkimi tymi pakietami i użyć pakietu, z którym najlepiej się korzystasz. Aby na przykład uruchomić zapytanie, można wywołać funkcje, takie jak SparkR::sql, sparklyr::sdf_sqli dplyr::select. Czasami możesz wykonać operację tylko z jednym lub dwoma z tych pakietów, a wybrana operacja zależy od scenariusza użycia. Na przykład sposób wywoływania sparklyr::sdf_quantile różni się nieco od sposobu wywoływania dplyr::percentile_approxmetody , mimo że oba funkcje pełnią kwantyle calcuate.

Możesz użyć języka SQL jako mostka między platformą SparkR i interfejsem sparklyr. Na przykład możesz użyć SparkR::sql polecenia , aby wykonywać zapytania dotyczące tabel tworzonych za pomocą interfejsu sparklyr. Do wykonywania zapytań dotyczących tabel tworzonych za pomocą aparatu SparkR można użyć sparklyr::sdf_sql polecenia . Kod dplyr jest zawsze tłumaczony na język SQL w pamięci przed jego uruchomieniem. Zobacz też Współdziałanie interfejsu API i Tłumaczenie SQL.

Ładowanie sparkR, sparklyr i dplyr

Pakiety SparkR, sparklyr i dplyr są zawarte w środowisku Databricks Runtime zainstalowanym w klastrach usługi Azure Databricks. W związku z tym nie trzeba wywoływać zwykłych install.package pakietów przed rozpoczęciem wywoływania tych pakietów. Jednak nadal należy załadować te pakiety za pomocą library polecenia . Na przykład z poziomu notesu języka R w obszarze roboczym usługi Azure Databricks uruchom następujący kod w komórce notesu, aby załadować usługę SparkR, sparklyr i dplyr:

library(SparkR)
library(sparklyr)
library(dplyr)

Połączenie sparklyr do klastra

Po załadowaniu narzędzia sparklyr należy wywołać metodę sparklyr::spark_connect , aby nawiązać połączenie z klastrem, określając metodę databricks połączenia. Na przykład uruchom następujący kod w komórce notesu, aby nawiązać połączenie z klastrem hostujący notes:

sc <- spark_connect(method = "databricks")

Z kolei notes usługi Azure Databricks już ustanawia SparkSession klaster do użycia z usługą SparkR, więc nie musisz wywoływać SparkR::sparkR.session przed rozpoczęciem wywoływania aparatu SparkR.

Przekazywanie pliku danych JSON do obszaru roboczego

Wiele przykładów kodu w tym artykule jest opartych na danych w określonej lokalizacji w obszarze roboczym usługi Azure Databricks z określonymi nazwami kolumn i typami danych. Dane dla tego przykładu kodu pochodzą z pliku JSON o nazwie book.json z usługi GitHub. Aby pobrać ten plik i przekazać go do obszaru roboczego:

  1. Przejdź do pliku books.json w usłudze GitHub i użyj edytora tekstów, aby skopiować jego zawartość do pliku o nazwie books.json gdzieś na komputerze lokalnym.
  2. Na pasku bocznym obszaru roboczego usługi Azure Databricks kliknij pozycję Wykaz.
  3. Kliknij pozycję Utwórz tabelę.
  4. Na karcie Przekaż plik upuść plik z komputera lokalnego do pola Upuść books.json pliki, aby przekazać. Możesz też wybrać przycisk przeglądania i przejść do pliku z komputera lokalnego books.json .

Domyślnie usługa Azure Databricks przekazuje plik lokalny books.json do lokalizacji DBFS w obszarze roboczym ze ścieżką /FileStore/tables/books.json.

Nie klikaj pozycji Utwórz tabelę za pomocą interfejsu użytkownika lub Utwórz tabelę w notesie. Przykłady kodu w tym artykule używają danych w przekazanym books.json pliku w tej lokalizacji systemu plików DBFS.

Odczytywanie danych JSON do ramki danych

Służy sparklyr::spark_read_json do odczytywania przekazanego pliku JSON do ramki danych, określania połączenia, ścieżki do pliku JSON i nazwy wewnętrznej reprezentacji danych w tabeli wewnętrznej. W tym przykładzie należy określić, że book.json plik zawiera wiele wierszy. Określenie schematu kolumn jest tutaj opcjonalne. W przeciwnym razie interfejs sparklyr domyślnie wywnioskuje schemat kolumn. Na przykład uruchom następujący kod w komórce notesu, aby odczytać przekazane dane pliku JSON do ramki danych o nazwie jsonDF:

jsonDF <- spark_read_json(
  sc      = sc,
  name    = "jsonTable",
  path    = "/FileStore/tables/books.json",
  options = list("multiLine" = TRUE),
  columns = c(
    author    = "character",
    country   = "character",
    imageLink = "character",
    language  = "character",
    link      = "character",
    pages     = "integer",
    title     = "character",
    year      = "integer"
  )
)

Możesz użyć SparkR::headmetody , SparkR::showlub sparklyr::collect , aby wydrukować pierwsze wiersze ramki danych. Domyślnie drukuje pierwsze sześć wierszy domyślnie head . show i collect wyświetl pierwsze 10 wierszy. Na przykład uruchom następujący kod w komórce notesu, aby wydrukować pierwsze wiersze ramki danych o nazwie jsonDF:

head(jsonDF)

# Source: spark<?> [?? x 8]
#   author                  country        image…¹ langu…² link  pages title  year
#   <chr>                   <chr>          <chr>   <chr>   <chr> <int> <chr> <int>
# 1 Chinua Achebe           Nigeria        images… English "htt…   209 Thin…  1958
# 2 Hans Christian Andersen Denmark        images… Danish  "htt…   784 Fair…  1836
# 3 Dante Alighieri         Italy          images… Italian "htt…   928 The …  1315
# 4 Unknown                 Sumer and Akk… images… Akkadi… "htt…   160 The … -1700
# 5 Unknown                 Achaemenid Em… images… Hebrew  "htt…   176 The …  -600
# 6 Unknown                 India/Iran/Ir… images… Arabic  "htt…   288 One …  1200
# … with abbreviated variable names ¹​imageLink, ²​language

show(jsonDF)

# Source: spark<jsonTable> [?? x 8]
#    author                  country       image…¹ langu…² link  pages title  year
#    <chr>                   <chr>         <chr>   <chr>   <chr> <int> <chr> <int>
#  1 Chinua Achebe           Nigeria       images… English "htt…   209 Thin…  1958
#  2 Hans Christian Andersen Denmark       images… Danish  "htt…   784 Fair…  1836
#  3 Dante Alighieri         Italy         images… Italian "htt…   928 The …  1315
#  4 Unknown                 Sumer and Ak… images… Akkadi… "htt…   160 The … -1700
#  5 Unknown                 Achaemenid E… images… Hebrew  "htt…   176 The …  -600
#  6 Unknown                 India/Iran/I… images… Arabic  "htt…   288 One …  1200
#  7 Unknown                 Iceland       images… Old No… "htt…   384 Njál…  1350
#  8 Jane Austen             United Kingd… images… English "htt…   226 Prid…  1813
#  9 Honoré de Balzac        France        images… French  "htt…   443 Le P…  1835
# 10 Samuel Beckett          Republic of … images… French… "htt…   256 Moll…  1952
# … with more rows, and abbreviated variable names ¹​imageLink, ²​language
# ℹ Use `print(n = ...)` to see more rows

collect(jsonDF)

# A tibble: 100 × 8
#    author                  country       image…¹ langu…² link  pages title  year
#    <chr>                   <chr>         <chr>   <chr>   <chr> <int> <chr> <int>
#  1 Chinua Achebe           Nigeria       images… English "htt…   209 Thin…  1958
#  2 Hans Christian Andersen Denmark       images… Danish  "htt…   784 Fair…  1836
#  3 Dante Alighieri         Italy         images… Italian "htt…   928 The …  1315
#  4 Unknown                 Sumer and Ak… images… Akkadi… "htt…   160 The … -1700
#  5 Unknown                 Achaemenid E… images… Hebrew  "htt…   176 The …  -600
#  6 Unknown                 India/Iran/I… images… Arabic  "htt…   288 One …  1200
#  7 Unknown                 Iceland       images… Old No… "htt…   384 Njál…  1350
#  8 Jane Austen             United Kingd… images… English "htt…   226 Prid…  1813
#  9 Honoré de Balzac        France        images… French  "htt…   443 Le P…  1835
# 10 Samuel Beckett          Republic of … images… French… "htt…   256 Moll…  1952
# … with 90 more rows, and abbreviated variable names ¹​imageLink, ²​language
# ℹ Use `print(n = ...)` to see more rows

Uruchamianie zapytań SQL i zapisywanie w tabeli i odczytywanie ich z tabeli

Za pomocą funkcji dplyr można uruchamiać zapytania SQL w ramce danych. Na przykład uruchom następujący kod w komórce notesu, aby użyć dplyr::group_by polecenia i dployr::count pobrać liczby autorów z ramki danych o nazwie jsonDF. Użyj funkcji dplyr::arrange i dplyr::desc , aby posortować wynik w kolejności malejącej według liczb. Następnie domyślnie wydrukuj pierwsze 10 wierszy.

group_by(jsonDF, author) %>%
  count() %>%
  arrange(desc(n))

# Source:     spark<?> [?? x 2]
# Ordered by: desc(n)
#    author                     n
#    <chr>                  <dbl>
#  1 Fyodor Dostoevsky          4
#  2 Unknown                    4
#  3 Leo Tolstoy                3
#  4 Franz Kafka                3
#  5 William Shakespeare        3
#  6 William Faulkner           2
#  7 Gustave Flaubert           2
#  8 Homer                      2
#  9 Gabriel García Márquez     2
# 10 Thomas Mann                2
# … with more rows
# ℹ Use `print(n = ...)` to see more rows

Następnie możesz użyć sparklyr::spark_write_table polecenia , aby zapisać wynik w tabeli w usłudze Azure Databricks. Na przykład uruchom następujący kod w komórce notesu, aby ponownie uruchomić zapytanie, a następnie zapisz wynik w tabeli o nazwie json_books_agg:

group_by(jsonDF, author) %>%
  count() %>%
  arrange(desc(n)) %>%
  spark_write_table(
    name = "json_books_agg",
    mode = "overwrite"
  )

Aby sprawdzić, czy tabela została utworzona, możesz użyć polecenia sparklyr::sdf_sql wraz z poleceniem SparkR::showDF , aby wyświetlić dane tabeli. Na przykład uruchom następujący kod w komórce notesu, aby wykonać zapytanie względem tabeli w ramce danych, a następnie użyj polecenia sparklyr::collect , aby wydrukować pierwsze 10 wierszy ramki danych domyślnie:

collect(sdf_sql(sc, "SELECT * FROM json_books_agg"))

# A tibble: 82 × 2
#    author                     n
#    <chr>                  <dbl>
#  1 Fyodor Dostoevsky          4
#  2 Unknown                    4
#  3 Leo Tolstoy                3
#  4 Franz Kafka                3
#  5 William Shakespeare        3
#  6 William Faulkner           2
#  7 Homer                      2
#  8 Gustave Flaubert           2
#  9 Gabriel García Márquez     2
# 10 Thomas Mann                2
# … with 72 more rows
# ℹ Use `print(n = ...)` to see more rows

Możesz również użyć sparklyr::spark_read_table polecenia , aby zrobić coś podobnego. Na przykład uruchom następujący kod w komórce notesu, aby wykonać zapytanie względem poprzedniej ramki danych o nazwie jsonDF w ramce danych, a następnie użyj polecenia sparklyr::collect , aby wydrukować pierwsze 10 wierszy ramki danych domyślnie:

fromTable <- spark_read_table(
  sc   = sc,
  name = "json_books_agg"
)

collect(fromTable)

# A tibble: 82 × 2
#    author                     n
#    <chr>                  <dbl>
#  1 Fyodor Dostoevsky          4
#  2 Unknown                    4
#  3 Leo Tolstoy                3
#  4 Franz Kafka                3
#  5 William Shakespeare        3
#  6 William Faulkner           2
#  7 Homer                      2
#  8 Gustave Flaubert           2
#  9 Gabriel García Márquez     2
# 10 Thomas Mann                2
# … with 72 more rows
# ℹ Use `print(n = ...)` to see more rows

Dodawanie kolumn i wartości kolumn obliczeniowych w ramce danych

Za pomocą funkcji dplyr można dodawać kolumny do ramek danych i wartości kolumn obliczeniowych.

Na przykład uruchom następujący kod w komórce notesu, aby pobrać zawartość ramki danych o nazwie jsonDF. Użyj dplyr::mutate polecenia , aby dodać kolumnę o nazwie todayi wypełnić tę nową kolumnę bieżącym znacznikiem czasu. Następnie zapisz te elementy w nowej ramce danych o nazwie withDate i użyj polecenia dplyr::collect , aby wydrukować domyślnie pierwsze 10 wierszy nowej ramki danych.

Uwaga

dplyr::mutate Akceptuje tylko argumenty zgodne z wbudowanymi funkcjami programu Hive (znanymi również jako funkcje zdefiniowane przez użytkownika) i wbudowanymi funkcjami agregacji (znanymi również jako FUNKCJE UDAFs). Aby uzyskać ogólne informacje, zobacz Hive Functions. Aby uzyskać informacje o funkcjach związanych z datą w tej sekcji, zobacz Funkcje daty.

withDate <- jsonDF %>%
  mutate(today = current_timestamp())

collect(withDate)

# A tibble: 100 × 9
#    author    country image…¹ langu…² link  pages title  year today
#    <chr>     <chr>   <chr>   <chr>   <chr> <int> <chr> <int> <dttm>
#  1 Chinua A… Nigeria images… English "htt…   209 Thin…  1958 2022-09-27 21:32:59
#  2 Hans Chr… Denmark images… Danish  "htt…   784 Fair…  1836 2022-09-27 21:32:59
#  3 Dante Al… Italy   images… Italian "htt…   928 The …  1315 2022-09-27 21:32:59
#  4 Unknown   Sumer … images… Akkadi… "htt…   160 The … -1700 2022-09-27 21:32:59
#  5 Unknown   Achaem… images… Hebrew  "htt…   176 The …  -600 2022-09-27 21:32:59
#  6 Unknown   India/… images… Arabic  "htt…   288 One …  1200 2022-09-27 21:32:59
#  7 Unknown   Iceland images… Old No… "htt…   384 Njál…  1350 2022-09-27 21:32:59
#  8 Jane Aus… United… images… English "htt…   226 Prid…  1813 2022-09-27 21:32:59
#  9 Honoré d… France  images… French  "htt…   443 Le P…  1835 2022-09-27 21:32:59
# 10 Samuel B… Republ… images… French… "htt…   256 Moll…  1952 2022-09-27 21:32:59
# … with 90 more rows, and abbreviated variable names ¹​imageLink, ²​language
# ℹ Use `print(n = ...)` to see more rows

Teraz użyj polecenia dplyr::mutate , aby dodać dwie kolejne kolumny do zawartości withDate ramki danych. Nowe month kolumny i year zawierają numerowy miesiąc i rok z kolumny today . Następnie zapisz te elementy w nowej ramce danych o nazwie withMMyyyyi użyj polecenia dplyr::select wraz z poleceniem authormonthdplyr::collecttitle, i year kolumny pierwszych dziesięciu wierszy nowej ramki danych domyślnie:

withMMyyyy <- withDate %>%
  mutate(month = month(today),
         year  = year(today))

collect(select(withMMyyyy, c("author", "title", "month", "year")))

# A tibble: 100 × 4
#    author                  title                                     month  year
#    <chr>                   <chr>                                     <int> <int>
#  1 Chinua Achebe           Things Fall Apart                             9  2022
#  2 Hans Christian Andersen Fairy tales                                   9  2022
#  3 Dante Alighieri         The Divine Comedy                             9  2022
#  4 Unknown                 The Epic Of Gilgamesh                         9  2022
#  5 Unknown                 The Book Of Job                               9  2022
#  6 Unknown                 One Thousand and One Nights                   9  2022
#  7 Unknown                 Njál's Saga                                   9  2022
#  8 Jane Austen             Pride and Prejudice                           9  2022
#  9 Honoré de Balzac        Le Père Goriot                                9  2022
# 10 Samuel Beckett          Molloy, Malone Dies, The Unnamable, the …     9  2022
# … with 90 more rows
# ℹ Use `print(n = ...)` to see more rows

Teraz użyj polecenia dplyr::mutate , aby dodać dwie kolejne kolumny do zawartości withMMyyyy ramki danych. Nowe formatted_date kolumny zawierają yyyy-MM-dd część z today kolumny, a nowa day kolumna zawiera dzień liczbowy z nowej formatted_date kolumny. Następnie zapisz te elementy w nowej ramce danych o nazwie withUnixTimestampi użyj polecenia dplyr::select wraz z poleceniem titledplyr::collectformatted_date, i day kolumny pierwszych dziesięciu wierszy nowej ramki danych domyślnie:

withUnixTimestamp <- withMMyyyy %>%
  mutate(formatted_date = date_format(today, "yyyy-MM-dd"),
         day            = dayofmonth(formatted_date))

collect(select(withUnixTimestamp, c("title", "formatted_date", "day")))

# A tibble: 100 × 3
#    title                                           formatted_date   day
#    <chr>                                           <chr>          <int>
#  1 Things Fall Apart                               2022-09-27        27
#  2 Fairy tales                                     2022-09-27        27
#  3 The Divine Comedy                               2022-09-27        27
#  4 The Epic Of Gilgamesh                           2022-09-27        27
#  5 The Book Of Job                                 2022-09-27        27
#  6 One Thousand and One Nights                     2022-09-27        27
#  7 Njál's Saga                                     2022-09-27        27
#  8 Pride and Prejudice                             2022-09-27        27
#  9 Le Père Goriot                                  2022-09-27        27
# 10 Molloy, Malone Dies, The Unnamable, the trilogy 2022-09-27        27
# … with 90 more rows
# ℹ Use `print(n = ...)` to see more rows

Tworzenie widoku tymczasowego

Możesz utworzyć nazwane widoki tymczasowe w pamięci, które są oparte na istniejących ramkach danych. Na przykład uruchom następujący kod w komórce notesu, aby użyć SparkR::createOrReplaceTempView polecenia w celu pobrania zawartości poprzedniej ramki danych o nazwie i utworzenia tymczasowego widoku z niego o nazwie jsonTabletimestampTable. Następnie użyj polecenia sparklyr::spark_read_table , aby odczytać zawartość widoku tymczasowego. Użyj sparklyr::collect polecenia , aby wydrukować pierwsze 10 wierszy tabeli tymczasowej domyślnie:

createOrReplaceTempView(withTimestampDF, viewName = "timestampTable")

spark_read_table(
  sc = sc,
  name = "timestampTable"
) %>% collect()

# A tibble: 100 × 10
#    author    country image…¹ langu…² link  pages title  year today
#    <chr>     <chr>   <chr>   <chr>   <chr> <int> <chr> <int> <dttm>
#  1 Chinua A… Nigeria images… English "htt…   209 Thin…  1958 2022-09-27 21:11:56
#  2 Hans Chr… Denmark images… Danish  "htt…   784 Fair…  1836 2022-09-27 21:11:56
#  3 Dante Al… Italy   images… Italian "htt…   928 The …  1315 2022-09-27 21:11:56
#  4 Unknown   Sumer … images… Akkadi… "htt…   160 The … -1700 2022-09-27 21:11:56
#  5 Unknown   Achaem… images… Hebrew  "htt…   176 The …  -600 2022-09-27 21:11:56
#  6 Unknown   India/… images… Arabic  "htt…   288 One …  1200 2022-09-27 21:11:56
#  7 Unknown   Iceland images… Old No… "htt…   384 Njál…  1350 2022-09-27 21:11:56
#  8 Jane Aus… United… images… English "htt…   226 Prid…  1813 2022-09-27 21:11:56
#  9 Honoré d… France  images… French  "htt…   443 Le P…  1835 2022-09-27 21:11:56
# 10 Samuel B… Republ… images… French… "htt…   256 Moll…  1952 2022-09-27 21:11:56
# … with 90 more rows, 1 more variable: month <chr>, and abbreviated variable
#   names ¹​imageLink, ²​language
# ℹ Use `print(n = ...)` to see more rows, and `colnames()` to see all variable names

Przeprowadzanie analizy statystycznej na ramce danych

Do analizy statystycznej można używać interfejsu sparklyr wraz z dplyr.

Na przykład utwórz ramkę danych do uruchamiania statystyk. W tym celu uruchom następujący kod w komórce notesu, aby użyć sparklyr::sdf_copy_to go do zapisania zawartości iris zestawu danych wbudowanego w język R w ramce danych o nazwie iris. Użyj sparklyr::sdf_collect polecenia , aby wydrukować pierwsze 10 wierszy tabeli tymczasowej domyślnie:

irisDF <- sdf_copy_to(
  sc        = sc,
  x         = iris,
  name      = "iris",
  overwrite = TRUE
)

sdf_collect(irisDF, "row-wise")

# A tibble: 150 × 5
#    Sepal_Length Sepal_Width Petal_Length Petal_Width Species
#           <dbl>       <dbl>        <dbl>       <dbl> <chr>
#  1          5.1         3.5          1.4         0.2 setosa
#  2          4.9         3            1.4         0.2 setosa
#  3          4.7         3.2          1.3         0.2 setosa
#  4          4.6         3.1          1.5         0.2 setosa
#  5          5           3.6          1.4         0.2 setosa
#  6          5.4         3.9          1.7         0.4 setosa
#  7          4.6         3.4          1.4         0.3 setosa
#  8          5           3.4          1.5         0.2 setosa
#  9          4.4         2.9          1.4         0.2 setosa
# 10          4.9         3.1          1.5         0.1 setosa
# … with 140 more rows
# ℹ Use `print(n = ...)` to see more rows

Teraz użyj polecenia dplyr::group_by , aby pogrupować wiersze według kolumny Species . Użyj polecenia dplyr::summarize , dplyr::percentile_approx aby obliczyć statystyki podsumowania według 25, 50, 75 i 100 kwantyli Sepal_Length kolumny według Species. Użyj sparklyr::collect wydruku wyników:

Uwaga

dplyr::summarize Akceptuje tylko argumenty zgodne z wbudowanymi funkcjami programu Hive (znanymi również jako funkcje zdefiniowane przez użytkownika) i wbudowanymi funkcjami agregacji (znanymi również jako FUNKCJE UDAFs). Aby uzyskać ogólne informacje, zobacz Hive Functions. Aby uzyskać informacje o percentile_approxsystemie, zobacz Wbudowane funkcje agregujące (UDAF).

quantileDF <- irisDF %>%
  group_by(Species) %>%
  summarize(
    quantile_25th = percentile_approx(
      Sepal_Length,
      0.25
    ),
    quantile_50th = percentile_approx(
      Sepal_Length,
      0.50
    ),
    quantile_75th = percentile_approx(
      Sepal_Length,
      0.75
    ),
    quantile_100th = percentile_approx(
      Sepal_Length,
      1.0
    )
  )

collect(quantileDF)

# A tibble: 3 × 5
#   Species    quantile_25th quantile_50th quantile_75th quantile_100th
#   <chr>              <dbl>         <dbl>         <dbl>          <dbl>
# 1 virginica            6.2           6.5           6.9            7.9
# 2 versicolor           5.6           5.9           6.3            7
# 3 setosa               4.8           5             5.2            5.8

Podobne wyniki można obliczyć, na przykład przy użyciu polecenia sparklyr::sdf_quantile:

print(sdf_quantile(
  x = irisDF %>%
    filter(Species == "virginica"),
  column = "Sepal_Length",
  probabilities = c(0.25, 0.5, 0.75, 1.0)
))

# 25%  50%  75% 100%
# 6.2  6.5  6.9  7.9