Sdílet prostřednictvím


Práce s datovými rámci a tabulkami v jazyce R

Tento článek popisuje, jak používat balíčky R, jako jsou SparkR, sparklyr a dplyr pro práci s R data.frames, Spark DataFrames a tabulky v paměti.

Mějte na paměti, že při práci se SparkR, sparklyr a dplyr můžete zjistit, že můžete dokončit konkrétní operaci se všemi těmito balíčky a můžete použít balíček, se kterým jste nejpohodlnější. Například ke spuštění dotazu můžete volat funkce, jako SparkR::sqlje , sparklyr::sdf_sqla dplyr::select. Jindy může být možné dokončit operaci jenom s jedním nebo dvěma z těchto balíčků a operace, kterou zvolíte, závisí na vašem scénáři použití. Například způsob volání se mírně liší od způsobu volání sparklyr::sdf_quantiledplyr::percentile_approx, i když obě funkce kalkulují quantiles.

SQL můžete použít jako most mezi SparkR a sparklyr. Můžete například použít SparkR::sql k dotazování tabulek, které vytvoříte pomocí sparklyr. Můžete použít sparklyr::sdf_sql k dotazování tabulek, které vytvoříte pomocí SparkR. Kód dplyr se před spuštěním vždy přeloží do SQL v paměti. Viz také interoperabilita rozhraní API a překlad SQL.

Load SparkR, sparklyr a dplyr

Balíčky SparkR, sparklyr a dplyr jsou součástí modulu Databricks Runtime, který je nainstalovaný v clusterech Azure Databricks. Proto před zahájením volání těchto balíčků nemusíte volat obvyklým install.package způsobem. Tyto balíčky library však musíte načíst nejprve. Například z poznámkového bloku R v pracovním prostoru Azure Databricks spusťte v buňce poznámkového bloku následující kód, který načte SparkR, sparklyr a dplyr:

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

Připojení sparklyr do clusteru

Po načtení sparklyru je nutné volat sparklyr::spark_connect pro připojení ke clusteru a zadat metodu databricks připojení. Například spuštěním následujícího kódu v buňce poznámkového bloku se připojte ke clusteru, který je hostitelem poznámkového bloku:

sc <- spark_connect(method = "databricks")

Poznámkový blok Azure Databricks už naopak vytvoří SparkSession v clusteru cluster pro použití se SparkR, takže před zahájením volání SparkR nemusíte volat SparkR::sparkR.session .

Nahrání datového souboru JSON do pracovního prostoru

Mnoho příkladů kódu v tomto článku vychází z dat v určitém umístění v pracovním prostoru Azure Databricks s konkrétními názvy sloupců a datovými typy. Data pro tento příklad kódu pocházejí ze souboru JSON s názvem book.json z GitHubu. Pokud chcete tento soubor získat a nahrát ho do pracovního prostoru:

  1. Přejděte do souboru books.json na GitHubu a pomocí textového editoru zkopírujte jeho obsah do souboru pojmenovaného books.json někde na místním počítači.
  2. Na bočním panelu pracovního prostoru Azure Databricks klikněte na Katalog.
  3. Klikněte na Vytvořit tabulku.
  4. Na kartě Nahrát soubor přetáhněte books.json soubor z místního počítače do pole Pro nahrání souborů. Nebo kliknutím přejděte na books.json soubor z místního počítače.

Azure Databricks ve výchozím nastavení nahraje místní books.json soubor do umístění DBFS ve vašem pracovním prostoru s cestou /FileStore/tables/books.json.

V poznámkovém bloku neklikejte na Vytvořit tabulku s uživatelským rozhraním ani na Vytvořit tabulku. Příklady kódu v tomto článku používají data v nahraném books.json souboru v tomto umístění DBFS.

Čtení dat JSON do datového rámce

Slouží sparklyr::spark_read_json ke čtení nahraného souboru JSON do datového rámce, určení připojení, cesty k souboru JSON a názvu pro interní reprezentaci dat v tabulce. V tomto příkladu book.json musíte určit, že soubor obsahuje více řádků. Zadání schématu sloupců je zde volitelné. Jinak sparklyr ve výchozím nastavení odvodí schéma sloupců. Například spuštěním následujícího kódu v buňce poznámkového bloku načtěte data nahraného souboru JSON do datového rámce s názvem 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"
  )
)

Můžete použít SparkR::head, SparkR::shownebo sparklyr::collect vytisknout první řádky datového rámce. Ve výchozím nastavení head vytiskne prvních šest řádků. show a collect vytiskněte prvních 10 řádků. Například spuštěním následujícího kódu v buňce poznámkového bloku vytiskněte první řádky datového rámce s názvem 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

Spouštění dotazů SQL a zápis do tabulky a čtení z tabulky

Pomocí funkcí dplyr můžete spouštět dotazy SQL na datovém rámci. Spusťte například následující kód v buňce poznámkového bloku, který chcete použít dplyr::group_by , a dployr::count získejte počty podle autora z datového rámce s názvem jsonDF. dplyr::desc Výsledek můžete dplyr::arrange seřadit sestupně podle počtu. Potom ve výchozím nastavení vytiskněte prvních 10 řádků.

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

Výsledek pak můžete použít sparklyr::spark_write_table k zápisu výsledku do tabulky v Azure Databricks. Například spuštěním následujícího kódu v buňce poznámkového bloku znovu spusťte dotaz a pak napište výsledek do tabulky s názvem json_books_agg:

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

Pokud chcete ověřit, že byla tabulka vytvořená, můžete ji použít sparklyr::sdf_sql společně SparkR::showDF se zobrazením dat tabulky. Například spuštěním následujícího kódu v buňce poznámkového bloku zadejte dotaz na tabulku do datového rámce a pak použijte sparklyr::collect k tisku prvních 10 řádků datového rámce ve výchozím nastavení:

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

Můžete také použít sparklyr::spark_read_table něco podobného. Například spuštěním následujícího kódu v buňce poznámkového bloku zadejte dotaz na předchozí datový rámec pojmenovaný jsonDF do datového rámce a potom použijte sparklyr::collect k tisku prvních 10 řádků datového rámce ve výchozím nastavení:

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

Přidání sloupců a výpočetních hodnot sloupců v datovém rámci

Funkce dplyr můžete použít k přidání sloupců do datových rámců a k výpočtu hodnot sloupců.

Například spuštěním následujícího kódu v buňce poznámkového bloku získejte obsah datového rámce s názvem jsonDF. Slouží dplyr::mutate k přidání sloupce s názvem todaya vyplnění tohoto nového sloupce aktuálním časovým razítkem. Potom tento obsah zapište do nového datového rámce s názvem withDate a ve výchozím nastavení použijte dplyr::collect k tisku prvních 10 řádků nového datového rámce.

Poznámka:

dplyr::mutate Přijímá pouze argumenty, které odpovídají předdefinovaným funkcím Hive (označovaným také jako UDF) a integrovaným agregačním funkcím (označovaným také jako UDAF). Obecné informace najdete v tématu Funkce Hive. Informace o funkcích souvisejících s datem v této části najdete v tématu Funkce data.

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

Teď můžete dplyr::mutate do obsahu datového withDate rámce přidat dva další sloupce. Nové month sloupce a year sloupce obsahují číselný měsíc a rok ze today sloupce. Potom napište tento obsah do nového datového rámce s názvem withMMyyyy, a použijte dplyr::select spolu s dplyr::collect tiskem author, monthtitlea year sloupce prvních deset řádků nového datového rámce ve výchozím nastavení:

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

Teď můžete dplyr::mutate do obsahu datového withMMyyyy rámce přidat dva další sloupce. Nové formatted_date sloupce obsahují yyyy-MM-dd část ze today sloupce, zatímco nový day sloupec obsahuje číselný den z nového formatted_date sloupce. Potom napište tento obsah do nového datového rámce s názvem withUnixTimestamp, a použijte dplyr::select spolu s dplyr::collect tiskem title, formatted_datea day sloupce prvních deset řádků nového datového rámce ve výchozím nastavení:

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

Vytvoření dočasného zobrazení

Můžete vytvořit pojmenovaná dočasná zobrazení v paměti, která jsou založená na existujících datových rámcích. Spuštěním následujícího kódu v buňce SparkR::createOrReplaceTempView poznámkového bloku můžete například získat obsah předchozího datového rámce s názvem jsonTable a vytvořit z něj dočasné zobrazení s názvem timestampTable. Pak se používá sparklyr::spark_read_table ke čtení obsahu dočasného zobrazení. Slouží sparklyr::collect k tisku prvních 10 řádků dočasné tabulky ve výchozím nastavení:

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

Provádění statistické analýzy datového rámce

Minigrafyr můžete použít společně s dplyr pro statistické analýzy.

Můžete například vytvořit datový rámec pro spouštění statistik. Uděláte to tak, že v buňce poznámkového bloku spustíte následující kód, který se použije sparklyr::sdf_copy_to k zápisu obsahu iris datové sady, která je integrovaná v jazyce R do datového rámce s názvem iris. Slouží sparklyr::sdf_collect k tisku prvních 10 řádků dočasné tabulky ve výchozím nastavení:

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

Teď slouží dplyr::group_by k seskupení řádků podle Species sloupce. Společně dplyr::summarize s dplyr::percentile_approx tím můžete vypočítat souhrnné statistiky podle 25. , 50. , 75. a 100. kvantových Sepal_Length hodnot sloupce podle Species. Použijte sparklyr::collect tisk výsledků:

Poznámka:

dplyr::summarize Přijímá pouze argumenty, které odpovídají předdefinovaným funkcím Hive (označovaným také jako UDF) a integrovaným agregačním funkcím (označovaným také jako UDAF). Obecné informace najdete v tématu Funkce Hive. Informace o percentile_approxfunkci UDAF naleznete v tématu Předdefinované agregační funkce(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

Podobné výsledky se dají vypočítat například pomocí 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