Udostępnij za pośrednictwem


Praca z ramkami danych i tabelami w języku R

Ważny

Usługa SparkR w usłudze Databricks jest przestarzała w środowisku Databricks Runtime 16.0 lub nowszym. Databricks zaleca zamiast tego używanie sparklyr.

W tym artykule opisano sposób używania pakietów języka R, takich jak SparkR, sparklyri dplyr do pracy z data.frameR, ramek danych Sparki tabel w pamięci.

Pamiętaj, że podczas pracy z pakietami SparkR, sparklyr i dplyr możesz stwierdzić, że jesteś w stanie ukończyć określoną operację z każdym z tych pakietów i użyć tego, z którego korzystasz najchętniej. 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_approx, mimo że obie funkcje obliczają kwantyle.

Możesz użyć języka SQL jako mostka między platformą SparkR i interfejsem sparklyr. Na przykład można użyć SparkR::sql do wykonywania zapytań dotyczących tabel tworzonych za pomocą interfejsu sparklyr. Możesz użyć sparklyr::sdf_sql do wykonywania zapytań dotyczących tabel tworzonych za pomocą aparatu SparkR. Kod dplyr jest zawsze przekształcany na SQL w pamięci przed jego uruchomieniem. Zobacz również współdziałanie interfejsu API i SQL Translation.

Załaduj 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 przed rozpoczęciem wywoływania tych pakietów. Jednak najpierw nadal należy załadować te pakiety z library. 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)

Łączenie sparklyr z klastrem

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

sc <- spark_connect(method = "databricks")

Natomiast notebook Azure Databricks już ustanawia SparkSession w klastrze do użycia z SparkR, więc nie trzeba wywoływać SparkR::sparkR.session przed rozpoczęciem korzystania z SparkR.

Prześlij plik danych JSON do swojego 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 poziomu usługi GitHub. Aby pobrać ten plik i wgrać go w obszar roboczy:

  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ę Catalog.
  3. Kliknij pozycję Utwórz tabelę.
  4. Na karcie Przesyłanie pliku upuść plik books.json z lokalnego komputera do pola Upuść pliki, aby przesłać. Możesz też wybrać kliknij, aby przeglądaći przejdź do pliku books.json z komputera lokalnego.

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

Nie klikaj Utwórz Tabelę za pomocą UI lub Utwórz Tabelę w Notesie. Przykłady kodu w tym artykule wykorzystują dane z przesłanego pliku books.json w lokalizacji DBFS.

Odczytywanie danych JSON do ramki danych

Użyj sparklyr::spark_read_json, aby odczytać przesłany plik JSON do DataFrame, określając połączenie, ścieżkę do pliku JSON i nazwę wewnętrznej tabelarycznej reprezentacji danych. W tym przykładzie należy określić, że plik book.json 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ć załadowane dane pliku JSON do obiektu DataFrame 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"
  )
)

Aby wydrukować pierwsze wiersze ramki danych, można użyć SparkR::head, SparkR::showlub sparklyr::collect. Domyślnie head domyślnie drukuje pierwsze sześć wierszy. show i collect drukują 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 i dployr::count, aby pobrać liczby autorów z ramki danych o nazwie jsonDF. Użyj dplyr::arrange i dplyr::desc, aby posortować wynik w kolejności malejącej według liczby. 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, aby zapisać wynik w tabeli w usłudze Azure Databricks. Uruchom na przykład 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ć sparklyr::sdf_sql wraz z 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 sparklyr::collect, aby wydrukować domyślnie pierwsze 10 wierszy ramki danych:

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, aby zrobić coś podobnego. Na przykład uruchom poniższy kod w komórce notesu, aby wykonać zapytanie dotyczące ramki danych o nazwie jsonDF, a następnie użyj sparklyr::collect, aby domyślnie wydrukować pierwsze 10 wierszy tej ramki danych.

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 obliczać wartości kolumn.

Na przykład wykonaj następujący kod w komórce notatnika, aby pobrać zawartość ramki danych o nazwie jsonDF. Użyj dplyr::mutate, 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 dplyr::collect, aby wydrukować domyślnie pierwsze 10 wierszy nowej ramki danych.

Notatka

dplyr::mutate akceptuje tylko argumenty zgodne z wbudowanymi funkcjami programu Hive (znanymi również jako UDF) i wbudowanymi funkcjami agregacyjnymi (znanymi również jako UDAF). Aby uzyskać ogólne informacje, więcej informacji znajdziesz w funkcjach Hive. Aby uzyskać informacje o funkcjach związanych z datą w tej sekcji, zobacz Date Functions.

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 dplyr::mutate, aby dodać dwie kolejne kolumny do zawartości withDate DataFrame. Nowe kolumny month i year zawierają numericzny miesiąc i rok z kolumny today. Następnie zapisz te elementy w nowej ramce danych o nazwie withMMyyyyi użyj dplyr::select wraz z dplyr::collect, aby wyświetlić kolumny author, title, month i year pierwszych dziesięciu wierszy nowej ramki danych:

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 dplyr::mutate, aby dodać dwie kolejne kolumny do zawartości withMMyyyy DataFrame. Nowe kolumny formatted_date zawierają część yyyy-MM-dd z kolumny today, a nowa kolumna day zawiera dzień liczbowy z nowej kolumny formatted_date. Następnie zapisz te elementy w nowej ramce danych o nazwie withUnixTimestampi użyj dplyr::select wraz z dplyr::collect, aby wyświetlić kolumny title, formatted_datei day pierwszych dziesięciu wierszy nowej ramki danych:

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 do pobrania zawartości poprzedniego DataFrame o nazwie jsonTable i utworzyć z niego tymczasowy widok o nazwie timestampTable. Następnie użyj sparklyr::spark_read_table, aby odczytać zawartość widoku tymczasowego. Użyj sparklyr::collect, aby domyślnie wydrukować pierwsze 10 wierszy tabeli tymczasowej:

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 analiz statystycznych można używać sparklyr z dplyr.

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

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 dplyr::group_by, aby pogrupować wiersze według kolumny Species. Użyj dplyr::summarize wraz z dplyr::percentile_approx, aby obliczyć statystyki podsumowania dla 25., 50., 75. i 100. kwantyla kolumny Sepal_Length zgodnie z Species. Użyj sparklyr::collect wydrukuj wyniki:

Notatka

dplyr::summarize akceptuje tylko argumenty zgodne z wbudowanymi funkcjami programu Hive (znanymi również jako UDF) i wbudowanymi funkcjami agregacyjnymi (znanymi również jako UDAF). Aby uzyskać ogólne informacje, więcej informacji znajdziesz w funkcjach Hive. Aby uzyskać informacje o percentile_approx, 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 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