Partager via


Utiliser des DataFrames et des tables dans R

Cet article explique comment utiliser des packages R tels que SparkR, sparklyr et dplyr pour utiliser des tables R data.frames, Spark DataFrames et en mémoire.

Notez que lorsque vous travaillez avec SparkR, sparklyr et dplyr, vous pouvez constater que vous pouvez effectuer une opération particulière avec tous ces packages, et vous pouvez utiliser le package avec lequel vous êtes le plus à l’aise. Par exemple, pour exécuter une requête, vous pouvez appeler des fonctions telles que SparkR::sql, sparklyr::sdf_sql et dplyr::select. À d’autres moments, vous pouvez effectuer une opération avec un ou deux de ces packages, et l’opération que vous choisissez dépend de votre scénario d’utilisation. Par exemple, la façon dont vous appelez sparklyr::sdf_quantile diffère légèrement de la façon dont vous appelez dplyr::percentile_approx, même si les deux fonctions calculent des quantiles.

Vous pouvez utiliser SQL comme pont entre SparkR et sparklyr. Par exemple, vous pouvez utiliser SparkR::sql pour interroger des tables que vous créez avec sparklyr. Vous pouvez utiliser sparklyr::sdf_sql pour interroger des tables que vous créez avec SparkR. Et le code dplyr est toujours traduit en SQL en mémoire avant son exécution. Consultez également Interopérabilité des API et Traduction SQL.

Charger SparkR, sparklyr et dplyr

Les packages SparkR, sparklyr et dplyr sont inclus dans Databricks Runtime installé sur des clusters Azure Databricks. Par conséquent, vous n’avez pas besoin d’appeler le install.package habituel avant de commencer à appeler ces packages. Toutefois, vous devez toujours charger ces packages avec library en premier. Par exemple, à partir d’un notebook R dans un espace de travail Azure Databricks, exécutez le code suivant dans une cellule de notebook pour charger SparkR, sparklyr et dplyr :

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

Connecter sparklyr à un cluster

Une fois que vous avez chargé sparklyr, vous devez appeler sparklyr::spark_connect pour vous connecter au cluster, en spécifiant la méthode de connexion databricks. Par exemple, exécutez le code suivant dans une cellule de notebook pour vous connecter au cluster qui héberge le notebook :

sc <- spark_connect(method = "databricks")

En revanche, un notebook Azure Databricks établit déjà un SparkSession sur le cluster à utiliser avec SparkR. Vous n’avez donc pas besoin d’appeler SparkR::sparkR.session avant de commencer à appeler SparkR.

Charger un fichier de données JSON dans votre espace de travail

De nombreux exemples de code de cet article sont basés sur des données à un emplacement spécifique dans votre espace de travail Azure Databricks, avec des noms de colonnes et des types de données spécifiques. Les données de cet exemple de code proviennent d’un fichier JSON nommé book.json de GitHub. Pour obtenir ce fichier et le charger dans votre espace de travail :

  1. Accédez au fichier books.json sur GitHub et utilisez un éditeur de texte pour copier son contenu dans un fichier nommé books.json quelque part sur votre ordinateur local.
  2. Dans la barre latérale de votre espace de travail Azure Databricks, cliquez sur Catalogue.
  3. Cliquez sur Créer une table.
  4. Sous l’onglet Charger un fichier, déposez le fichier books.json de votre ordinateur local vers la zone Déposer les fichiers à charger. Vous pouvez également cliquer pour parcourir le fichier et parcourir le fichier books.json à partir de votre ordinateur local.

Par défaut, Azure Databricks charge votre fichier books.json local à l’emplacement DBFS dans votre espace de travail avec le chemin d’accès /FileStore/tables/books.json.

Ne cliquez pas sur Créer une table avec l’interface utilisateur ou Créer une table dans Notebook. Les exemples de code de cet article utilisent les données du fichier books.json chargé à cet emplacement DBFS.

Lire les données JSON dans un DataFrame

Utilisez sparklyr::spark_read_json pour lire le fichier JSON téléchargé dans un DataFrame, en spécifiant la connexion, le chemin d'accès au fichier JSON et un nom pour la représentation de la table interne des données. Pour cet exemple, vous devez spécifier que le fichier book.json contient plusieurs lignes. La spécification du schéma des colonnes est ici facultative. Sinon, sparklyr déduit le schéma des colonnes par défaut. Par exemple, exécutez le code suivant dans une cellule de notebook pour lire les données du fichier JSON chargé dans un DataFrame nommé 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"
  )
)

Vous pouvez utiliser SparkR::head, SparkR::show ou sparklyr::collect pour imprimer les premières lignes d’un DataFrame. Par défaut, head imprime les six premières lignes par défaut. show et collect impriment les 10 premières lignes. Par exemple, exécutez le code suivant dans une cellule de notebook pour imprimer les premières lignes du DataFrame nommé 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

Exécuter des requêtes SQL et écrire dans et lire à partir d’une table

Vous pouvez utiliser des fonctions dplyr pour exécuter des requêtes SQL sur un DataFrame. Par exemple, exécutez le code suivant dans une cellule de notebook pour utiliser dplyr::group_by et dployr::count afin d’obtenir des nombres par auteur à partir du DataFrame nommé jsonDF. Utilisez dplyr::arrange et dplyr::desc pour trier le résultat dans l’ordre décroissant par nombre. Imprimez ensuite les 10 premières lignes par défaut.

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

Vous pouvez ensuite utiliser sparklyr::spark_write_table pour écrire le résultat dans une table dans Azure Databricks. Par exemple, exécutez le code suivant dans une cellule de notebook pour réexécuter la requête, puis écrivez le résultat dans une table nommée json_books_agg :

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

Pour vérifier que la table a été créée, vous pouvez ensuite utiliser sparklyr::sdf_sql ainsi que SparkR::showDF pour afficher les données de la table. Par exemple, exécutez le code suivant dans une cellule de notebook pour interroger la table dans un DataFrame, puis utilisez sparklyr::collect pour imprimer les 10 premières lignes du DataFrame par défaut :

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

Vous pouvez également utiliser sparklyr::spark_read_table pour faire quelque chose de similaire. Par exemple, exécutez le code suivant dans une cellule de notebook pour interroger le DataFrame précédent nommé jsonDF dans un DataFrame, puis utilisez sparklyr::collect pour imprimer les 10 premières lignes du DataFrame par défaut :

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

Ajouter des colonnes et calculer des valeurs de colonne dans un DataFrame

Vous pouvez utiliser des fonctions dplyr pour ajouter des colonnes aux DataFrames et calculer les valeurs des colonnes.

Par exemple, exécutez le code suivant dans une cellule de notebook pour obtenir le contenu du DataFrame nommé jsonDF. Utilisez dplyr::mutate pour ajouter une colonne nommée today et remplissez cette nouvelle colonne avec l’horodatage actuel. Ensuite, écrivez ce contenu dans un nouveau DataFrame nommé withDate et utilisez dplyr::collect pour imprimer les 10 premières lignes de DataFrame par défaut.

Notes

dplyr::mutate accepte uniquement les arguments conformes aux fonctions intégrées de Hive (également appelées UDF) et aux fonctions d’agrégation intégrées (également appelées UDAF). Pour plus d’informations, consultez Fonctions Hive. Pour plus d’informations sur les fonctions liées à la date dans cette section, consultez Fonctions de date.

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

Utilisez maintenant dplyr::mutate pour ajouter deux colonnes supplémentaires au contenu du DataFrame withDate. Les nouvelles colonnes month et year contiennent le mois et l’année numériques de la colonne today. Ensuite, écrivez ce contenu dans un nouveau DataFrame nommé withMMyyyy, puis utilisez dplyr::select avec dplyr::collect pour imprimer les colonnes author, title, month et year des dix premières lignes du nouveau DataFrame par défaut :

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

Utilisez maintenant dplyr::mutate pour ajouter deux colonnes supplémentaires au contenu du DataFrame withMMyyyy. Les nouvelles colonnes formatted_date contiennent la partie yyyy-MM-dd de la colonne today, tandis que la nouvelle colonne day contient le jour numérique de la nouvelle colonne formatted_date. Ensuite, écrivez ce contenu dans un nouveau DataFrame nommé withUnixTimestamp, puis utilisez dplyr::select avec dplyr::collect pour imprimer les colonnes title, formatted_date et day des dix premières lignes du nouveau DataFrame par défaut :

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

Créer un affichage temporaire

Vous pouvez créer des affichages temporaires nommées en mémoire basées sur des DataFrames existants. Par exemple, exécutez le code suivant dans une cellule de notebook pour utiliser SparkR::createOrReplaceTempView afin d’obtenir le contenu du DataFrame précédent nommé jsonTable et créer un affichage temporaire de celle-ci nommé timestampTable. Ensuite, utilisez sparklyr::spark_read_table pour lire le contenu de l’affichage temporaire. Utilisez sparklyr::collect pour imprimer les 10 premières lignes de la table temporaire par défaut :

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

Effectuer une analyse statistique sur un DataFrame

Vous pouvez utiliser sparklyr avec dplyr pour les analyses statistiques.

Par exemple, créez un DataFrame pour exécuter des statistiques. Pour ce faire, exécutez le code suivant dans une cellule de notebook pour utiliser sparklyr::sdf_copy_to afin d’écrire le contenu du jeu de données iris intégré à R dans un DataFrame nommé iris. Utilisez sparklyr::sdf_collect pour imprimer les 10 premières lignes de la table temporaire par défaut :

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

Utilisez maintenant dplyr::group_by pour regrouper les lignes par la colonne Species. Utilisez dplyr::summarize avec dplyr::percentile_approx pour calculer les statistiques récapitulatives par les 25e, le 50e, le 75e et le 100e quantiles de la colonne Sepal_Length par Species. Utilisez sparklyr::collect pour imprimer les résultats :

Notes

dplyr::summarize accepte uniquement les arguments conformes aux fonctions intégrées de Hive (également appelées UDF) et aux fonctions d’agrégation intégrées (également appelées UDAF). Pour plus d’informations, consultez Fonctions Hive. Pour plus d’informations sur percentile_approx, consultez Fonctions d’agrégation intégrées (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

Les résultats similaires peuvent être calculés, par exemple, à l’aide de 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