다음을 통해 공유


R에서 DataFrame 및 테이블 작업

중요하다

Databricks의 SparkR은 Databricks Runtime 16.0 이상에서 더 이상 사용되지 . Databricks는 대신 sparklyr을 사용할 것을 권장합니다.

이 문서에서는 SparkR, sparklyrdplyr 같은 R 패키지를 사용하여 R data.frame, Spark DataFrames및 메모리 내 테이블을 사용하는 방법을 설명합니다.

SparkR, sparklyr, 그리고 dplyr과 함께 작업할 때, 특정 작업을 이들 모든 패키지로 완료할 수 있으며, 당신이 가장 편안하게 느끼는 패키지를 사용할 수 있음을 알 수 있습니다. 예를 들어 쿼리를 실행하려면 SparkR::sql, sparklyr::sdf_sqldplyr::select같은 함수를 호출할 수 있습니다. 다른 경우에는 이러한 패키지 중 하나 또는 두 개만 사용하여 작업을 완료할 수 있으며 선택한 작업은 사용 시나리오에 따라 달라집니다. 예를 들어 sparklyr::sdf_quantile 호출하는 방법은 두 함수가 양자를 계산하더라도 dplyr::percentile_approx호출하는 방식과 약간 다릅니다.

SparkR과 sparklyr 사이의 브리지로 SQL을 사용할 수 있습니다. 예를 들어 SparkR::sql 사용하여 sparklyr로 만든 테이블을 쿼리할 수 있습니다. sparklyr::sdf_sql 사용하여 SparkR로 만든 테이블을 쿼리할 수 있습니다. 또한 dplyr 코드는 실행되기 전에 항상 메모리에서 SQL로 변환됩니다. API 상호 운용성SQL 번역참조하세요.

SparkR, sparklyr 및 dplyr 불러오기

SparkR, sparklyr 및 dplyr 패키지는 Azure Databricks 클러스터에 설치된 Databricks 런타임에 포함됩니다. 따라서 이러한 패키지 호출을 시작하기 전에 일반적인 install.package 호출할 필요가 없습니다. 그러나 먼저 library로 이러한 패키지를 로드해야 합니다. 예를 들어 Azure Databricks 작업 영역의 R Notebook 내에서 Notebook 셀에서 다음 코드를 실행하여 SparkR, sparklyr 및 dplyr를 로드합니다.

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

클러스터에 sparklyr 연결

sparklyr를 로드한 후 sparklyr::spark_connect 호출하여 databricks 연결 방법을 지정하여 클러스터에 연결해야 합니다. 예를 들어 Notebook 셀에서 다음 코드를 실행하여 Notebook을 호스트하는 클러스터에 연결합니다.

sc <- spark_connect(method = "databricks")

반면, Azure Databricks Notebook은 SparkR에서 사용하기 위해 클러스터에 이미 SparkSession 설정하므로 SparkR 호출을 시작하기 전에 SparkR::sparkR.session 호출할 필요가 없습니다.

작업 영역에 JSON 데이터 파일 업로드

이 문서의 많은 코드 예제는 특정 열 이름 및 데이터 형식을 사용하여 Azure Databricks 작업 영역의 특정 위치에 있는 데이터를 기반으로 합니다. 이 코드 예제의 데이터는 GitHub 내에서 book.json 이름이 지정된 JSON 파일에서 시작됩니다. 이 파일을 가져와 작업 영역에 업로드하려면 다음을 수행합니다.

  1. GitHub의 books.json 파일로 이동하고 텍스트 편집기를 사용하여 해당 콘텐츠를 로컬 컴퓨터의 어딘가에 books.json 파일에 복사합니다.
  2. Azure Databricks 작업 영역 사이드바에서 카탈로그클릭합니다.
  3. 테이블 만들기을 클릭하십시오.
  4. 파일 업로드 탭에서 로컬 컴퓨터의 books.json 파일을 '업로드 파일 드롭' 상자에 놓으세요. 또는 을(를) 클릭하여로 이동한 후, 로컬 컴퓨터에서 books.json 파일을 찾아보세요.

기본적으로 Azure Databricks는 경로 books.json사용하여 작업 영역의 DBFS 위치에 로컬 /FileStore/tables/books.json 파일을 업로드합니다.

UI의 '테이블 만들기' 를 클릭하거나 Notebook의 '테이블 만들기' 를 클릭하지 마십시오. 이 문서의 코드 예제에서는 이 DBFS 위치에 업로드된 books.json 파일의 데이터를 사용합니다.

DataFrame으로 JSON 데이터 읽기

sparklyr::spark_read_json 사용하여 데이터 프레임에 업로드된 JSON 파일을 읽고 연결, JSON 파일 경로 및 데이터의 내부 테이블 표현 이름을 지정합니다. 이 예제에서는 book.json 파일에 여러 줄이 포함되도록 지정해야 합니다. 여기에서 열의 스키마를 지정하는 것은 선택 사항입니다. 그렇지 않으면 sparklyr는 기본적으로 열의 스키마를 유추합니다. 예를 들어 Notebook 셀에서 다음 코드를 실행하여 업로드된 JSON 파일의 데이터를 jsonDF이라는 DataFrame으로 읽습니다.

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"
  )
)

SparkR::head, SparkR::show또는 sparklyr::collect 사용하여 DataFrame의 첫 번째 행을 인쇄할 수 있습니다. 기본적으로 head 처음 6개의 행을 기본적으로 인쇄합니다. showcollect이 각각 처음 10개 행을 출력합니다. 예를 들어 Notebook 셀에서 다음 코드를 실행하여 jsonDF라는 DataFrame의 첫 번째 행을 인쇄합니다.

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

SQL 쿼리를 실행하고 테이블에서 쓰기 및 읽기

dplyr 함수를 사용하여 DataFrame에서 SQL 쿼리를 실행할 수 있습니다. 예를 들어 Notebook 셀에서 다음 코드를 실행하여 jsonDF라는 DataFrame에서 작성자별로 개수를 얻기 위해 dplyr::group_bydployr::count을 사용합니다. dplyr::arrangedplyr::desc 사용하여 결과를 카운트별로 내림차순으로 정렬합니다. 그런 다음, 기본적으로 처음 10개의 행을 인쇄합니다.

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

그런 다음 sparklyr::spark_write_table 사용하여 Azure Databricks의 테이블에 결과를 쓸 수 있습니다. 예를 들어 Notebook 셀에서 다음 코드를 실행하여 쿼리를 다시 실행한 다음 결과를 json_books_agg테이블에 씁니다.

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

테이블이 생성되었는지 확인하려면, sparklyr::sdf_sqlSparkR::showDF을 사용하여 테이블의 데이터를 표시할 수 있습니다. 예를 들어 Notebook 셀에서 다음 코드를 실행하여 테이블을 DataFrame으로 쿼리한 다음 sparklyr::collect 사용하여 기본적으로 DataFrame의 처음 10개 행을 인쇄합니다.

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

sparklyr::spark_read_table 사용하여 비슷한 작업을 수행할 수도 있습니다. 예를 들어, Notebook 셀에서 다음 코드를 실행하여 jsonDF라는 이전 DataFrame을 쿼리하여 새로운 DataFrame으로 생성한 후, sparklyr::collect을 사용하여 기본적으로 새 DataFrame의 처음 10개 행을 출력합니다.

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

DataFrame에서 열 추가 및 열 값 계산

dplyr 함수를 사용하여 DataFrames에 열을 추가하고 열 값을 계산할 수 있습니다.

예를 들어 Notebook 셀에서 다음 코드를 실행하여 jsonDF이라는 DataFrame의 내용을 가져옵니다. dplyr::mutate 사용하여 today열을 추가하고 이 새 열을 현재 타임스탬프로 채웁니다. 그런 다음 이러한 내용을 withDate이라는 새 DataFrame에 쓰고 dplyr::collect 사용하여 기본적으로 새 DataFrame의 처음 10개 행을 인쇄합니다.

메모

dplyr::mutate Hive의 기본 제공 함수(UDF라고도 함) 및 기본 제공 집계 함수(UDAF라고도 함)를 준수하는 인수만 허용합니다. 일반적인 내용은 Hive 함수참조하세요. 이 섹션의 날짜 관련 함수에 대한 자세한 내용은 날짜 함수참조하세요.

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

이제 dplyr::mutate 사용하여 withDate DataFrame의 내용에 두 개의 열을 더 추가합니다. 새 monthyear 열에는 today 열의 숫자 월과 연도가 포함됩니다. 그런 다음 이러한 내용을 withMMyyyy이라는 새 DataFrame에 쓰고, dplyr::selectdplyr::collect를 함께 사용하여 기본적으로 새 DataFrame의 처음 10개 행의 author, title, monthyear 열을 출력합니다.

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

이제 dplyr::mutate 사용하여 withMMyyyy DataFrame의 내용에 두 개의 열을 더 추가합니다. 새 formatted_date 열에는 today 열의 yyyy-MM-dd 부분이 포함되며 새 day 열에는 새 formatted_date 열의 숫자 날짜가 포함됩니다. 그런 다음 이러한 내용을 withUnixTimestamp명명된 새 DataFrame에 쓰고 dplyr::selectdplyr::collect 사용하여 기본적으로 새 DataFrame의 처음 10개 행의 title, formatted_dateday 열을 인쇄합니다.

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

임시 보기 만들기

기존 데이터 프레임을 기반으로 하는 명명된 임시 뷰를 메모리에 만들 수 있습니다. 예를 들어, 노트북 셀에서 아래 코드를 실행하여 SparkR::createOrReplaceTempView을 사용해 jsonTable이라는 이전 DataFrame의 내용을 가져오고, 이를 timestampTable라는 이름의 임시 보기로 만드세요. 그런 다음 sparklyr::spark_read_table 사용하여 임시 보기의 내용을 읽습니다. sparklyr::collect 사용하여 임시 테이블의 처음 10개 행을 기본적으로 인쇄합니다.

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

DataFrame에 대한 통계 분석 수행

통계 분석에는 dplyr와 함께 sparklyr를 사용할 수 있습니다.

예를 들어 통계를 실행할 DataFrame을 만듭니다. 이렇게 하려면, Notebook 셀에서 다음 코드를 실행하여 sparklyr::sdf_copy_to를 사용하여 R에 기본 제공되는 iris 데이터 세트의 내용을 iris로 이름 붙인 DataFrame에 기록합니다. sparklyr::sdf_collect 사용하여 임시 테이블의 처음 10개 행을 기본적으로 인쇄합니다.

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

이제 dplyr::group_by 사용하여 행을 Species 열로 그룹화합니다. dplyr::summarizedplyr::percentile_approx과 함께 사용하여 Species별로 Sepal_Length 열의 25번째, 50번째, 75번째 및 100번째 분위수에 따른 요약 통계를 계산합니다. sparklyr::collect을 사용하여 결과를 출력하세요.

메모

dplyr::summarize Hive의 기본 제공 함수(UDF라고도 함) 및 기본 제공 집계 함수(UDAF라고도 함)를 준수하는 인수만 허용합니다. 일반적인 내용은 Hive 함수참조하세요. percentile_approx대한 자세한 내용은 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

예를 들어 다음과 같은 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