22  Arrow

22.1 Εισαγωγή

Τα αρχεία CSV έχουν σχεδιαστεί για να διαβάζονται εύκολα από τον άνθρωπο. Είναι μία καλή μορφή για ανταλλαγή πληροφορίας επειδή είναι πολύ απλά και μπορούν να διαβαστούν από κάθε εργαλείο. Τα αρχεία CSV όμως δεν είναι πολύ αποτελεσματικά: πρέπει να κάνετε αρκετή δουλειά για να διαβάσετε τα δεδομένα στην R. Σε αυτό το κεφάλαιο, θα μάθετε για μία ισχυρή εναλλακτική: τη μορφή parquet, μία μορφή που βασίζεται σε ανοιχτά πρότυπα και χρησιμοποιείται ευρέως από συστήματα διαχείρισης μεγάλων δεδομένων.

Θα συνδυάσουμε αρχεία parquet με το Apache Arrow, μία εργαλειοθήκη πολλαπλών γλωσσών, σχεδιασμένη για αποτελεσματική ανάλυση και μεταφορά μεγάλων συνόλων δεδομένων. Θα χρησιμοποιήσουμε το Apache Arrow μέσω του πακέτου arrow, το οποίο παρέχει ένα σύστημα υποστήριξης της dplyr που σας επιτρέπει να αναλύετε σύνολα δεδομένων μεγαλύτερα από τη μνήμη, χρησιμοποιώντας την γνωστή σύνταξη από το πακέτο dplyr. Ως πρόσθετο πλεονέκτημα, το arrow είναι εξαιρετικά γρήγορο: θα δείτε μερικά παραδείγματα αργότερα στο κεφάλαιο.

Τόσο το arrow όσο και το πακέτο dbplyr παρέχουν συστήματα υποστήριξης στο πακέτο dplyr, οπότε μπορεί να αναρωτιέστε πότε να χρησιμοποιήσετε το καθένα. Σε πολλές περιπτώσεις, αυτή η επιλογή έχει ήδη γίνει για εσάς, καθώς τα δεδομένα βρίσκονται ήδη σε μία βάση δεδομένων ή σε αρχεία parquet, οπότε θα θέλετε να εργαστείτε με αυτά ως έχουν. Εάν όμως ξεκινάτε με τα δικά σας δεδομένα (ίσως αρχεία CSV), μπορείτε είτε να τα φορτώσετε σε μία βάση δεδομένων είτε να τα μετατρέψετε σε parquet. Γενικά, είναι δύσκολο να γνωρίζουμε τι θα λειτουργήσει καλύτερα, επομένως στα πρώτα στάδια της ανάλυσής σας, θα σας ενθαρρύνουμε να δοκιμάσετε και τα δύο και να επιλέξετε αυτό που λειτουργεί καλύτερα για εσάς.

(Ένα μεγάλο ευχαριστώ στη Danielle Navarro που συνέβαλε στην αρχική έκδοση αυτού του κεφαλαίου.)

22.1.1 Προαπαιτούμενα

Σε αυτό το κεφάλαιο, θα συνεχίσουμε να χρησιμοποιούμε το tidyverse, και ιδιαίτερα το πακέτο dplyr, αλλά θα το συνδυάσουμε με το πακέτο arrow που έχει σχεδιαστεί ειδικά για εργασία με μεγάλα δεδομένα.

Αργότερα στο κεφάλαιο, θα δούμε επίσης κάποιες συνδέσεις μεταξύ arrow και duckdb, κι επομένως θα χρειαστούμε επίσης το πακέτο dbplyr και το duckdb.

library(dbplyr, warn.conflicts = FALSE)
library(duckdb)
#> Loading required package: DBI

22.2 Λήψη δεδομένων

Ξεκινάμε παίρνοντας ένα σύνολο δεδομένων αντάξιο αυτών των εργαλείων: ένα σύνολο δεδομένων από βιβλία που έχουν δανειστεί από τις δημόσιες βιβλιοθήκες του Σιάτλ. Είναι διαθέσιμο στο διαδίκτυο στη διεύθυνση data.seattle.gov/Community/Checkouts-by-Title/tmmm-ytt6. Αυτό το σύνολο δεδομένων περιέχει 41.389.465 γραμμές που σας λένε πόσες φορές κάθε βιβλίο έχει δανειστεί κάθε μήνα από τον Απρίλιο του 2005 έως τον Οκτώβριο του 2022.

Ο παρακάτω κώδικας θα σας δώσει ένα αποθηκευμένο αντίγραφο των δεδομένων. Τα δεδομένα είναι ένα αρχείο CSV 9 GB, επομένως θα χρειαστεί λίγος χρόνος για τη λήψη του. Συνιστώ ανεπιφύλακτα να χρησιμοποιήσετε το curl::multi_download() για να κατεβάζετε πολύ μεγάλα αρχεία, καθώς έχει κατασκευαστεί γι’ αυτόν ακριβώς τον σκοπό: σας δίνει μία γραμμή προόδου και μπορεί να συνεχίσει τη λήψη εάν διακοπεί.

dir.create("data", showWarnings = FALSE)

curl::multi_download(
  "https://r4ds.s3.us-west-2.amazonaws.com/seattle-library-checkouts.csv",
  "data/seattle-library-checkouts.csv",
  resume = TRUE
)

22.3 Άνοιγμα ενός συνόλου δεδομένων

Ας ξεκινήσουμε ρίχνοντας μία ματιά στα δεδομένα. Με μέγεθος 9 GB, αυτό το αρχείο είναι αρκετά μεγάλο, οπότε πιθανώς να μην θέλουμε να το φορτώσουμε ολόκληρο στη μνήμη. Ένας καλός εμπειρικός κανόνας είναι ότι συνήθως θέλετε να έχετε τουλάχιστον διπλάσια μνήμη από το μέγεθος των δεδομένων, και πολλοί φορητοί υπολογιστές φτάνουν μέχρι τα 16 GB. Αυτό σημαίνει ότι θέλουμε να αποφύγουμε την read_csv() και προτιμάμε να χρησιμοποιήσουμε την arrow::open_dataset():

seattle_csv <- open_dataset(
  sources = "data/seattle-library-checkouts.csv", 
  col_types = schema(ISBN = string()),
  format = "csv"
)

Τι συμβαίνει όταν εκτελείται αυτός ο κώδικας;
Η open_dataset() θα σκανάρει μερικές χιλιάδες γραμμές για να καταλάβει τη δομή του συνόλου δεδομένων. Η στήλη ISBN περιέχει κενές τιμές για τις πρώτες 80.000 σειρές, επομένως πρέπει να καθορίσουμε τον τύπο στήλης για να βοηθήσουμε το arrow να επεξεργαστεί τη δομή των δεδομένων. Μόλις η open_dataset() σαρώσει τα δεδομένα, καταγράφει αυτό που βρέθηκε και σταματά. Θα διαβάζει περαιτέρω γραμμές μόνο όταν τις ζητάτε. Αυτά είναι τα μεταδεδομένα που βλέπουμε αν εκτυπώσουμε το seattle_csv:

seattle_csv
#> FileSystemDataset with 1 csv file
#> UsageClass: string
#> CheckoutType: string
#> MaterialType: string
#> CheckoutYear: int64
#> CheckoutMonth: int64
#> Checkouts: int64
#> Title: string
#> ISBN: string
#> Creator: string
#> Subjects: string
#> Publisher: string
#> PublicationYear: string

Η πρώτη γραμμή στην έξοδο σας λέει ότι το seattle_csv αποθηκεύεται τοπικά στο δίσκο ως ένα μεμονωμένο αρχείο CSV. θα φορτωθεί στη μνήμη μόνο όταν απαιτείται. Το υπόλοιπο της εξόδου σας λέει τον τύπο στήλης που έχει υπολογίσει το arrow για κάθε στήλη.

Μπορούμε να δούμε τι συμβαίνει στην πραγματικότητα με την glimpse(). Αυτό αποκαλύπτει ότι υπάρχουν ~41 εκατομμύρια γραμμές και 12 στήλες και, ακόμα, μας εμφανίζει και μερικές τιμές.

seattle_csv |> glimpse()
#> FileSystemDataset with 1 csv file
#> 41,389,465 rows x 12 columns
#> $ UsageClass      <string> "Physical", "Physical", "Digital", "Physical", "Ph…
#> $ CheckoutType    <string> "Horizon", "Horizon", "OverDrive", "Horizon", "Hor…
#> $ MaterialType    <string> "BOOK", "BOOK", "EBOOK", "BOOK", "SOUNDDISC", "BOO…
#> $ CheckoutYear     <int64> 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 20…
#> $ CheckoutMonth    <int64> 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,…
#> $ Checkouts        <int64> 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 2, 3, 2, 1, 3, 2,…
#> $ Title           <string> "Super rich : a guide to having it all / Russell S…
#> $ ISBN            <string> "", "", "", "", "", "", "", "", "", "", "", "", ""…
#> $ Creator         <string> "Simmons, Russell", "Barclay, James, 1965-", "Tim …
#> $ Subjects        <string> "Self realization, Conduct of life, Attitude Psych…
#> $ Publisher       <string> "Gotham Books,", "Pyr,", "Random House, Inc.", "Di…
#> $ PublicationYear <string> "c2011.", "2010.", "2015", "2005.", "c2004.", "c20…

Μπορούμε να αρχίσουμε να χρησιμοποιούμε αυτό το σύνολο δεδομένων με συναρτήσεις του πακέτου dplyr, χρησιμοποιώντας την collect() για να αναγκάσουμε το arrow να εκτελέσει τον υπολογισμό και να επιστρέψει κάποια δεδομένα. Για παράδειγμα, αυτός ο κωδικός μας λέει τον συνολικό αριθμό δανεισμών ανά έτος:

seattle_csv |> 
  group_by(CheckoutYear) |> 
  summarise(Checkouts = sum(Checkouts)) |> 
  arrange(CheckoutYear) |> 
  collect()
#> # A tibble: 18 × 2
#>   CheckoutYear Checkouts
#>          <int>     <int>
#> 1         2005   3798685
#> 2         2006   6599318
#> 3         2007   7126627
#> 4         2008   8438486
#> 5         2009   9135167
#> 6         2010   8608966
#> # ℹ 12 more rows

Χάρη στο arrow, αυτός ο κώδικας θα λειτουργεί ανεξάρτητα από το πόσο μεγάλο είναι το υποκείμενο σύνολο δεδομένων. Αλλά αυτή τη στιγμή είναι αρκετά αργός: στον υπολογιστή του Hadley, χρειάστηκαν ~10 δευτερόλεπτα για να τρέξει. Αυτό δεν είναι τρομερό δεδομένου του όγκου των δεδομένων που έχουμε, μπορούμε όμως να τα κάνουμε πολύ πιο γρήγορα μεταβαίνοντας σε μία καλύτερη μορφή.

22.4 Η μορφή parquet

Για να διευκολύνουμε την εργασία με αυτά τα δεδομένα, ας αλλάξουμε στη μορφή αρχείου parquet και ας τα χωρίσουμε σε πολλαπλά αρχεία. Οι παρακάτω ενότητες θα σας παρουσιάσουν πρώτα το parquet και την διαμέριση και, στη συνέχεια, θα εφαρμόσουν όσα μάθαμε στα δεδομένα της βιβλιοθήκης του Σιάτλ.

22.4.1 Πλεονεκτήματα της parquet

Όπως το CSV, έτσι και το parquet χρησιμοποιείται για δεδομένα σε μορφή πίνακα, αλλά αντί τα δεδομένα μας να είναι σε μία μορφή κειμένου που μπορείτε να διαβάσετε με οποιοδήποτε πρόγραμμα επεξεργασίας αρχείων, είναι μία προσαρμοσμένη δυαδική μορφή που έχει σχεδιαστεί ειδικά για τις ανάγκες των μεγάλων δεδομένων. Αυτό σημαίνει ότι:

  • Τα αρχεία parquet είναι συνήθως μικρότερα από το αντίστοιχο αρχείο CSV. Το parquet βασίζεται σε αποδοτικές κωδικοποιήσεις για να διατηρεί το μέγεθος του αρχείου χαμηλό και να υποστηρίζει τη συμπίεση αρχείων. Αυτό βοηθά εργασίες που αφορούν αρχεία parquet να γίνουν πιο γρήγορες επειδή υπάρχουν λιγότερα δεδομένα για μετακίνηση από τον δίσκο προς τη μνήμη.

  • Τα αρχεία parquet έχουν ένα σύστημα που επιτρέπει ευέλικτους τρόπους περιγραφής των τύπων δεδομένων. Όπως είπαμε στην Ενότητα 7.3, ένα αρχείο CSV δεν παρέχει πληροφορίες σχετικά με τους τύπους των στηλών του. Για παράδειγμα, ένα σύστημα αναγνώστης CSV πρέπει να μαντέψει εάν το “08-10-2022” πρέπει να αναλυθεί ως συμβολοσειρά ή ως ημερομηνία. Αντίθετα, τα αρχεία parquet αποθηκεύουν τα δεδομένα με τρόπο που καταγράφει και τον τύπο τους.

  • Τα αρχεία parquet είναι “προσαρμοσμένα σε στήλες”. Αυτό σημαίνει ότι είναι οργανωμένα στήλη προς στήλη, όπως το πλαίσιο δεδομένων της R. Αυτό συνήθως οδηγεί σε καλύτερη απόδοση για εργασίες ανάλυσης δεδομένων σε σύγκριση με αρχεία CSV, τα οποία είναι οργανωμένα σε γραμμές.

  • Τα αρχεία parquet είναι “σε κομμάτια”, γεγονός που καθιστά δυνατή την εργασία σε διαφορετικά μέρη του αρχείου ταυτόχρονα και, αν είστε τυχεροί, μπορείτε να παραλείψετε μερικά κομμάτια εντελώς.

Υπάρχει ένα βασικό μειονέκτημα στα αρχεία parquet: δεν είναι πλέον “αναγνώσιμα από τον άνθρωπο”, δηλαδή εάν κοιτάξετε ένα αρχείο parquet χρησιμοποιώντας την readr::read_file(), θα δείτε απλώς μία δέσμη ασυναρτησιών.

22.4.2 Διαμερισμός

Καθώς τα σύνολα δεδομένων γίνονται όλο και μεγαλύτερα, η αποθήκευση όλων των δεδομένων σε ένα μόνο αρχείο γίνεται όλο και πιο επίπονη, και είναι συχνά χρήσιμο μεγάλα σύνολα δεδομένων να χωρίζονται σε πολλαπλά αρχεία. Όταν αυτή η δόμηση γίνει έξυπνα, η στρατηγική αυτή μπορεί να οδηγήσει σε σημαντικές βελτιώσεις στην απόδοση, επειδή πολλές αναλύσεις θα απαιτούν μόνο ένα υποσύνολο των αρχείων.

Δεν υπάρχουν συγκεκριμένοι και γρήγοροι κανόνες σχετικά με τον τρόπο διαχωρισμού των δεδομένων σας: τα αποτελέσματα θα εξαρτηθούν από τα δεδομένα σας, τα μοτίβα πρόσβασης και τα συστήματα που διαβάζουν τα δεδομένα. Είναι πιθανό να χρειαστεί να κάνετε κάποιους πειραματισμούς προτού βρείτε τον ιδανικό διαχωρισμό για την περίπτωσή σας. Ως γενικό οδηγό, το arrow προτείνει να αποφεύγετε αρχεία μικρότερα από 20 MB και μεγαλύτερα από 2 GB και να αποφεύγετε διαμερίσματα που παράγουν περισσότερα από 10.000 αρχεία. Θα πρέπει επίσης να προσπαθήσετε να χωρίσετε τα αρχεία σύμφωνα με τις μεταβλητές που φιλτράρετε. Όπως θα δείτε σύντομα, αυτό επιτρέπει στο arrow να παραλείψει αρκετούς υπολογισμούς διαβάζοντας μόνο τα σχετικά αρχεία.

22.4.3 Ξαναγράφοντας τα δεδομένα της βιβλιοθήκης του Σιάτλ

Ας εφαρμόσουμε αυτές τις ιδέες στα δεδομένα της βιβλιοθήκης του Σιάτλ για να δούμε πως λειτουργούν στην πράξη. Θα κάνουμε τον διαχωρισμό με βάση τη στήλη CheckoutYear, καθώς είναι πιθανό ορισμένες αναλύσεις να θέλουν να εξετάσουν μόνο τα πρόσφατα δεδομένα και ο διαχωρισμός ανά έτος επιστρέφει 18 κομμάτια λογικού μεγέθους.

Για να ξαναγράψουμε τα δεδομένα ορίζουμε το διαμέρισμα χρησιμοποιώντας την dplyr::group_by() και, στη συνέχεια, αποθηκεύουμε τα διαμερίσματα σε έναν κατάλογο με την arrow::write_dataset(). Η write_dataset() έχει δύο σημαντικά ορίσματα: έναν κατάλογο στον οποίο θα δημιουργήσουμε τα αρχεία και τη μορφή που θα χρησιμοποιήσουμε.

pq_path <- "data/seattle-library-checkouts"
seattle_csv |>
  group_by(CheckoutYear) |>
  write_dataset(path = pq_path, format = "parquet")

Αυτό παίρνει περίπου ένα λεπτό για να τρέξει. Όπως θα δούμε σύντομα αυτή είναι μία αρχική επένδυση που αποδίδει καρπούς κάνοντας μελλοντικές εργασίες πολύ πολύ πιο γρήγορες.

Ας ρίξουμε μία ματιά σε αυτό που μόλις δημιουργήσαμε:

tibble(
  files = list.files(pq_path, recursive = TRUE),
  size_MB = file.size(file.path(pq_path, files)) / 1024^2
)
#> # A tibble: 18 × 2
#>   files                            size_MB
#>   <chr>                              <dbl>
#> 1 CheckoutYear=2005/part-0.parquet    109.
#> 2 CheckoutYear=2006/part-0.parquet    164.
#> 3 CheckoutYear=2007/part-0.parquet    178.
#> 4 CheckoutYear=2008/part-0.parquet    195.
#> 5 CheckoutYear=2009/part-0.parquet    214.
#> 6 CheckoutYear=2010/part-0.parquet    222.
#> # ℹ 12 more rows

Το αρχείο CSV μας με τα 9 GB έχει ξαναγραφτεί σε 18 αρχεία parquet. Τα ονόματα αρχείων χρησιμοποιούν έναν κανόνα “αυτο-περιγραφής” που χρησιμοποιείται από το Apache Hive. Διαμερίσματα τύπου Hive ονομάζουν φακέλους με έναν κανόνα “key=value”, έτσι, όπως μπορείτε να μαντέψετε, ο κατάλογος CheckoutYear=2005 περιέχει όλα τα δεδομένα όπου η CheckoutYear είναι 2005. Κάθε αρχείο είναι μεταξύ 100 και 300 MB και το συνολικό μέγεθος είναι τώρα περίπου 4 GB, λίγο περισσότερο από το μισό μέγεθος του αρχικού αρχείου CSV. Αναμενόμενο, καθώς το parquet είναι μία πολύ πιο αποτελεσματική μορφή αρχείου.

22.5 Συνδυάζοντας τα πακέτα dplyr και arrow

Αφού δημιουργήσαμε αυτά τα αρχεία parquet, τώρα θα πρέπει να τα διαβάσουμε ξανά. Χρησιμοποιούμε ξανά την open_dataset(), αλλά αυτή τη φορά της δίνουμε έναν κατάλογο:

seattle_pq <- open_dataset(pq_path)

Τώρα μπορούμε να γράψουμε τη ροή με το πακέτο dplyr. Για παράδειγμα, θα μπορούσαμε να μετρήσουμε τον συνολικό αριθμό βιβλίων που είχαν δανειστεί κάθε μήνα για τα τελευταία πέντε χρόνια:

query <- seattle_pq |> 
  filter(CheckoutYear >= 2018, MaterialType == "BOOK") |>
  group_by(CheckoutYear, CheckoutMonth) |>
  summarize(TotalCheckouts = sum(Checkouts)) |>
  arrange(CheckoutYear, CheckoutMonth)

Η σύνταξη κώδικα dplyr για δεδομένα arrow είναι εννοιολογικά παρόμοια με αυτή του πακέτου dbplyr, Κεφάλαιο 21: γράφετε κώδικα dplyr, ο οποίος μετατρέπεται αυτόματα σε ένα ερώτημα που κατανοεί η βιβλιοθήκη της Apache Arrow C++, και το οποίο ερώτημα στη συνέχεια εκτελείται όταν καλείτε την collect(). Εάν εκτυπώσουμε το αντικείμενο query, μπορούμε να δούμε μερικές πληροφορίες σχετικά με το τι περιμένουμε να επιστρέψει το Arrow όταν πραγματοποιηθεί η εκτέλεση:

query
#> FileSystemDataset (query)
#> CheckoutYear: int32
#> CheckoutMonth: int64
#> TotalCheckouts: int64
#> 
#> * Grouped by CheckoutYear
#> * Sorted by CheckoutYear [asc], CheckoutMonth [asc]
#> See $.data for the source Arrow object

Και μπορούμε να πάρουμε τα αποτελέσματα καλώντας την collect():

query |> collect()
#> # A tibble: 58 × 3
#> # Groups:   CheckoutYear [5]
#>   CheckoutYear CheckoutMonth TotalCheckouts
#>          <int>         <int>          <int>
#> 1         2018             1         355101
#> 2         2018             2         309813
#> 3         2018             3         344487
#> 4         2018             4         330988
#> 5         2018             5         318049
#> 6         2018             6         341825
#> # ℹ 52 more rows

Όπως και το dbplyr, έτσι και το arrow κατανοεί μόνο ορισμένες εκφράσεις της R, επομένως ενδέχεται να μην μπορείτε να γράψετε ακριβώς τον ίδιο κώδικα που θα γράφατε συνήθως. Ωστόσο, η λίστα των λειτουργιών που υποστηρίζονται είναι αρκετά εκτενής και συνεχίζει να αυξάνεται. Μπορείτε να βρείτε μία πλήρη λίστα με τις τρέχουσες υποστηριζόμενες συναρτήσεις στο ?acero.

22.5.1 Απόδοση

Ας ρίξουμε μία γρήγορη ματιά στο αντίκτυπο της απόδοσης που είχε η μετάβαση από CSV σε parquet. Αρχικά, ας ορίσουμε πόσο χρόνο χρειάζεται για να υπολογίσουμε τον αριθμό των βιβλίων που δανείζονται κάθε μήνα του 2021, όταν τα δεδομένα αποθηκεύονται ως ένα μεγάλο csv:

seattle_csv |> 
  filter(CheckoutYear == 2021, MaterialType == "BOOK") |>
  group_by(CheckoutMonth) |>
  summarize(TotalCheckouts = sum(Checkouts)) |>
  arrange(desc(CheckoutMonth)) |>
  collect() |> 
  system.time()
#>    user  system elapsed 
#>   8.932   0.775   8.580

Τώρα ας χρησιμοποιήσουμε τη νέα μας έκδοση του συνόλου δεδομένων, στην οποία τα δεδομένα δανεισμού της βιβλιοθήκης του Σιάτλ έχουν χωριστεί σε 18 μικρότερα αρχεία parquet:

seattle_pq |> 
  filter(CheckoutYear == 2021, MaterialType == "BOOK") |>
  group_by(CheckoutMonth) |>
  summarize(TotalCheckouts = sum(Checkouts)) |>
  arrange(desc(CheckoutMonth)) |>
  collect() |> 
  system.time()
#>    user  system elapsed 
#>   0.196   0.050   0.045

Η ~100x επιτάχυνση στην απόδοση αποδίδεται σε δύο παράγοντες: την διαμέριση πολλαπλών αρχείων και τη μορφή των μεμονωμένων αρχείων:

  • Η διαμέριση βελτιώνει την απόδοση επειδή το ερώτημα χρησιμοποιεί το CheckoutYear == 2021 για να φιλτράρει τα δεδομένα και το arrow είναι αρκετά έξυπνη ώστε να αναγνωρίζει ότι χρειάζεται να διαβάσει μόνο 1 από τα 18 αρχεία parquet.
  • Η μορφή parquet βελτιώνει την απόδοση, αποθηκεύοντας τα δεδομένα σε δυαδική μορφή, η οποία μπορεί να διαβαστεί πιο άμεσα στη μνήμη. Η κατά στήλη μορφή και τα εμπλουτισμένα μεταδεδομένα σημαίνουν ότι η arrow χρειάζεται μόνο να διαβάσει τις τέσσερις στήλες που χρησιμοποιούνται πραγματικά στο ερώτημα (CheckoutYear, MaterialType, CheckoutMonth και Checkouts).

Αυτή η τεράστια διαφορά στην απόδοση είναι η απάντηση στο γιατί συμφέρει να μετατρέψετε μεγάλα CSV σε parquet!

22.5.2 Συνδυάζοντας τα πακέτα duckdb και arrow

Υπάρχει ένα τελευταίο πλεονέκτημα του parquet και του arrow — είναι πολύ εύκολο να μετατρέψετε ένα σύνολο δεδομένων arrow σε βάση δεδομένων DuckDB (Κεφάλαιο 21) καλώντας την arrow::to_duckdb():

seattle_pq |> 
  to_duckdb() |>
  filter(CheckoutYear >= 2018, MaterialType == "BOOK") |>
  group_by(CheckoutYear) |>
  summarize(TotalCheckouts = sum(Checkouts)) |>
  arrange(desc(CheckoutYear)) |>
  collect()
#> Warning: Missing values are always removed in SQL aggregation functions.
#> Use `na.rm = TRUE` to silence this warning
#> This warning is displayed once every 8 hours.
#> # A tibble: 5 × 2
#>   CheckoutYear TotalCheckouts
#>          <int>          <dbl>
#> 1         2022        2431502
#> 2         2021        2266438
#> 3         2020        1241999
#> 4         2019        3931688
#> 5         2018        3987569

Το καλό με την to_duckdb() είναι ότι η μεταφορά δεν περιλαμβάνει αντιγραφή στη μνήμη, πράγμα που είναι και στόχος του οικοσυστήματος του arrow: να επιτρέπει συνεχείς μεταβάσεις από το ένα υπολογιστικό περιβάλλον στο άλλο.

22.5.3 Ασκήσεις

  1. Βρείτε το πιο δημοφιλές βιβλίο κάθε έτος.
  2. Ποιος συγγραφέας έχει τα περισσότερα βιβλία στο σύστημα της βιβλιοθήκης του Σιάτλ;
  3. Πώς έχουν αλλάξει οι δανεισμοί των βιβλίων έναντι των ηλεκτρονικών βιβλίων τα τελευταία 10 χρόνια;

22.6 Σύνοψη

Σε αυτό το κεφάλαιο, σας δόθηκε μία γεύση από το πακέτο arrow, το οποίο παρέχει ένα σύστημα υποστήριξης της dplyr για εργασία με μεγάλα σύνολα δεδομένων, αποθηκευμένα στο δίσκο. Μπορεί να λειτουργήσει με αρχεία CSV και είναι πολύ πιο γρήγορο αν μετατρέψετε τα δεδομένα σας σε parquet. Η parquet είναι μία δυαδική μορφή δεδομένων που έχει σχεδιαστεί ειδικά για ανάλυση δεδομένων σε σύγχρονους υπολογιστές. Πολύ λιγότερα εργαλεία μπορούν να λειτουργήσουν με αρχεία parquet σε σύγκριση με τα CSV, αλλά η διαμερισμένη, συμπιεσμένη και στηλοειδής δομή τους τα καθιστά πολύ πιο αποτελεσματικά στην ανάλυση.

Στη συνέχεια θα μάθετε για την πρώτη σας πηγή δεδομένων που δεν είναι σε μορφή πίνακα, την οποία θα χειριστείτε χρησιμοποιώντας εργαλεία που παρέχονται από το πακέτο tidyr. Θα επικεντρωθούμε σε δεδομένα που προέρχονται από αρχεία JSON, οι γενικές αρχές όμως ισχύουν για δεδομένα που έχουν ιεραρχική (ή δενδροειδή) μορφή ανεξάρτητα από την προέλευσή τους.