Dela via


Arbeta med DataFrames och tabeller i R

Viktig

SparkR i Databricks är inaktuell i Databricks Runtime 16.0 och senare. Databricks rekommenderar att du använder sparklyr i stället.

I den här artikeln beskrivs hur du använder R-paket som SparkR, sparklyroch dplyr för att arbeta med R data.frames, Spark DataFramesoch minnesinterna tabeller.

Observera att när du arbetar med SparkR, sparklyr och dplyr kan du upptäcka att du kan slutföra en viss åtgärd med alla dessa paket, och du kan använda det paket som du är mest bekväm med. Om du till exempel vill köra en fråga kan du anropa funktioner som SparkR::sql, sparklyr::sdf_sqloch dplyr::select. Vid andra tillfällen kanske du kan slutföra en åtgärd med bara ett eller två av dessa paket, och den åtgärd du väljer beror på ditt användningsscenario. Till exempel skiljer sig sättet du anropar sparklyr::sdf_quantile något från hur du anropar dplyr::percentile_approx, även om båda funktionerna beräknar kvantantiklar.

Du kan använda SQL som en brygga mellan SparkR och sparklyr. Du kan till exempel använda SparkR::sql för att fråga efter tabeller som du skapar med sparklyr. Du kan använda sparklyr::sdf_sql för att fråga efter tabeller som du skapar med SparkR. Och dplyr kod översätts alltid till SQL i minnet innan den körs. Se även API-samverkan och SQL Translation.

Läs in SparkR, sparklyr och dplyr

SparkR-, sparklyr- och dplyr-paketen ingår i Databricks Runtime som är installerat på Azure Databricks kluster. Därför behöver du inte anropa den vanliga install.package innan du kan börja anropa dessa paket. Du måste dock fortfarande läsa in dessa paket med library först. Från en R notebook- i en Azure Databricks-arbetsyta kör du till exempel följande kod i en notebook-cell för att läsa in SparkR, sparklyr och dplyr:

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

Ansluta sparklyr till ett kluster

När du har läst in sparklyr måste du anropa sparklyr::spark_connect för att ansluta till klustret och ange databricks som anslutningsmetod. Kör till exempel följande kod i en notebook-cell för att ansluta till klustret som är värd för notebook-filen:

sc <- spark_connect(method = "databricks")

Däremot upprättar en Azure Databricks-notebook redan en SparkSession i klustret för att använda med SparkR, så du behöver inte köra SparkR::sparkR.session innan du kan börja köra SparkR.

Ladda upp en JSON-datafil till din arbetsyta

Många av kodexemplen i den här artikeln baseras på data på en specifik plats på din Azure Databricks-arbetsyta, med specifika kolumnnamn och datatyper. Data för det här kodexemplet kommer från en JSON-fil med namnet book.json inifrån GitHub. Så här hämtar du den här filen och laddar upp den till din arbetsyta:

  1. Gå till den books.json filen på GitHub och använd en textredigerare för att kopiera innehållet till en fil med namnet books.json någonstans på den lokala datorn.
  2. I sidofältet för Azure Databricks-arbetsytan klickar du på Catalog.
  3. Klicka på Skapa tabell.
  4. På fliken Ladda upp fil släpper du filen books.json från den lokala datorn till rutan Släpp filer för att ladda upp. Eller välj klicka för att bläddra, och bläddra till books.json-filen från din lokala dator.

Som standard laddar Azure Databricks upp din lokala books.json-fil till DBFS- plats på arbetsytan med sökvägen /FileStore/tables/books.json.

Klicka inte på Skapa tabell med användargränssnittet eller Skapa tabell i notebooken. Kodexemplen i den här artikeln använder data i den uppladdade books.json-filen på den här DBFS-platsen.

Läs JSON-data till en DataFrame

Använd sparklyr::spark_read_json för att läsa den uppladdade JSON-filen till en DataFrame, ange anslutningen, sökvägen till JSON-filen och ett namn för den interna tabellrepresentationen av data. I det här exemplet måste du ange att filen book.json innehåller flera rader. Det är valfritt att ange kolumnernas schema här. Annars härleder sparklyr kolumnernas schema som standard. Kör till exempel följande kod i en notebook-cell för att läsa den uppladdade JSON-filens data till en DataFrame med namnet 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"
  )
)

Du kan använda SparkR::head, SparkR::showeller sparklyr::collect för att skriva ut de första raderna i en DataFrame. Som standard skriver head ut de första sex raderna som standard. show och collect skriva ut de första 10 raderna. Kör till exempel följande kod i en notebook-cell för att skriva ut de första raderna i DataFrame med namnet 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

Utför SQL-frågor och skriv till och läs från en tabell

Du kan använda dplyr-funktioner för att köra SQL-frågor på en DataFrame. Kör till exempel följande kod i en notebook-cell för att använda dplyr::group_by och dployr::count för att hämta antal av författare från DataFrame med namnet jsonDF. Använd dplyr::arrange och dplyr::desc för att sortera resultatet i fallande ordning efter antal. Skriv sedan ut de första 10 raderna som standard.

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

Du kan sedan använda sparklyr::spark_write_table för att skriva resultatet till en tabell i Azure Databricks. Kör till exempel följande kod i en notebook-cell för att köra frågan igen och skriv sedan resultatet till en tabell med namnet json_books_agg:

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

För att kontrollera att tabellen har skapats kan du sedan använda sparklyr::sdf_sql tillsammans med SparkR::showDF för att visa tabellens data. Kör till exempel följande kod i en notebook-cell för att fråga tabellen till en DataFrame och använd sedan sparklyr::collect för att skriva ut de första 10 raderna i DataFrame som standard:

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

Du kan också använda sparklyr::spark_read_table för att göra något liknande. Kör till exempel följande kod i en notebook-cell för att göra frågor mot den tidigare nämnda DataFrame jsonDF och omvandla den till en ny DataFrame. Använd sedan sparklyr::collect för att som standard skriva ut de första 10 raderna av DataFrame:

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

Lägga till kolumner och beräkningskolumnvärden i en DataFrame

Du kan använda dplyr-funktioner för att lägga till kolumner i DataFrames och för att beräkna kolumners värden.

Kör till exempel följande kod i en notebook-cell för att hämta innehållet i dataramen med namnet jsonDF. Använd dplyr::mutate om du vill lägga till en kolumn med namnet todayoch fylla den nya kolumnen med den aktuella tidsstämpeln. Skriv sedan innehållet till en ny DataFrame med namnet withDate och använd dplyr::collect för att skriva ut den nya DataFrames första 10 rader som standard.

Note

dplyr::mutate accepterar endast argument som överensstämmer med Hive:s inbyggda funktioner (även kallade UDF:er) och inbyggda aggregerade funktioner (även kallade UDAF:er). Allmän information finns i Hive Functions. Information om datumrelaterade funktioner i det här avsnittet finns i 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

Använd nu dplyr::mutate för att lägga till ytterligare två kolumner i innehållet i withDate DataFrame. De nya kolumnerna month och year innehåller den numeriska månaden och året från kolumnen today. Skriv sedan innehållet till en ny DataFrame med namnet withMMyyyyoch använd dplyr::select tillsammans med dplyr::collect för att skriva ut kolumnerna author, title, month och year i den nya DataFrame:s tio första rader som standard:

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

Använd nu dplyr::mutate för att lägga till ytterligare två kolumner i innehållet i withMMyyyy DataFrame. De nya formatted_date kolumnerna innehåller den yyyy-MM-dd delen från kolumnen today, medan den nya day-kolumnen innehåller den numeriska dagen från den nya formatted_date kolumnen. Skriv sedan innehållet till en ny DataFrame med namnet withUnixTimestampoch använd dplyr::select tillsammans med dplyr::collect för att skriva ut kolumnerna title, formatted_dateoch day i den nya DataFrame:s tio första rader som standard:

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

Skapa en tillfällig vy

Du kan skapa namngivna tillfälliga vyer i minnet som baseras på befintliga DataFrames. Kör till exempel följande kod i en notebook-cell för att använda SparkR::createOrReplaceTempView för att hämta innehållet i föregående DataFrame med namnet jsonTable och göra en tillfällig vy av den med namnet timestampTable. Använd sedan sparklyr::spark_read_table för att läsa innehållet i den temporära vyn. Använd sparklyr::collect för att skriva ut de första 10 raderna i den temporära tabellen som standard:

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

Utföra statistisk analys på en DataFrame

Du kan använda sparklyr tillsammans med dplyr för statistiska analyser.

Skapa till exempel en DataFrame att köra statistik på. Det gör du genom att köra följande kod i en notebook-cell för att använda sparklyr::sdf_copy_to för att skriva innehållet i den iris datauppsättning som är inbyggd i R till en dataram med namnet iris. Använd sparklyr::sdf_collect för att skriva ut de första 10 raderna i den temporära tabellen som standard:

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

Använd nu dplyr::group_by för att gruppera rader efter kolumnen Species. Använd dplyr::summarize tillsammans med dplyr::percentile_approx för att beräkna sammanfattningsstatistik efter den 25:e, 50:e, 75:e och 100:e kvantilen av Sepal_Length-kolumnen efter Species. Använd sparklyr::collect och skriv ut resultaten:

Note

dplyr::summarize accepterar endast argument som överensstämmer med Hive:s inbyggda funktioner (även kallade UDF:er) och inbyggda aggregerade funktioner (även kallade UDAF:er). Allmän information finns i Hive Functions. Information om percentile_approxfinns i Inbyggda aggregerade funktioner (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

Liknande resultat kan till exempel beräknas med hjälp av 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