if (!require("pacman")) install.packages("pacman")
::p_load(
pacman# file management
here, qs, # data wrangling
magrittr, janitor, # data analysis
easystats, sjmisc, # table visualization
gt, gtExtras, # visualization
ggpubr, ggwordcloud, # text analysis
tidytext, widyr,
openalexR, # load last to avoid masking issues
tidyverse )
Text processing with R
Session 08 - Exercise
Ziel der Anwendung: Textanalyse in R kennenlernen
- Auffrischung der Grundkenntnisse im Umgang mit R, tidyverse und ggplot2
- Typische Schritte der Textanalyse mit
tidytext
kennenlernen, von der Tokenisierung bis zur Visualisierung.
Background
Todays’s data basis: OpenAlex
Via API bzw. openalexR (Aria et al. 2024) gesammelte “works” der Datenbank OpenAlex mit Bezug zu Literaturriews in den Sozialwissenschaften zwischen 2013 und 2023
Detaillierte Informationen und Ergebnisse zur Suchquery finden Sie hier.
Preparation
Wichtige Information
- Bitte stellen Sie sicher, dass Sie das jeweilige R-Studio Projekt zur Übung geöffnet haben. Nur so funktionieren alle Dependencies korrekt.
- Um den einwandfreien Ablauf der Übung zu gewährleisten, wird für die Aufgaben auf eine eigenständige Datenerhebung verzichtet und ein Übungsdatensatz zu verfügung gestelt.
Packages
Import und Vorverarbeitung der Daten
# Import from local
<- qs::qread(here("data/session-07/openalex-review_works-2013_2023.qs"))
review_works
# Create correct data
<- review_works %>%
review_works_correct mutate(
# Create additional factor variables
publication_year_fct = as.factor(publication_year),
type_fct = as.factor(type)
)
🛠️ Praktische Anwendung
Achtung, bitte lesen!
- Bevor Sie mit der Arbeit an den folgenden 📋 Exercises beginnen, stellen Sie bitte sicher, dass Sie alle Chunks des Abschnitts Preparation gerendert haben. Das können Sie tun, indem Sie den “Run all chunks above”-Knopf
des nächsten Chunks benutzen.
- Bei Fragen zum Code lohnt sich ein Blick in den Showcase (.qmd oder .html). Beim Showcase handelt es sich um eine kompakte Darstellung des in der Präsentation verwenden R-Codes. Sie können das Showcase also nutzen, um sich die Code-Bausteine anzusehen, die für die R-Outputs auf den Slides benutzt wurden.
📋 Exercise 1: Neues Subsample
Ziel der Aufgabe
- Erstellung eines neuen Datensatzes
review_subsample_new
, der sich auf englischsprachig Bücher bzw. Buchrartikel beschränkt.
- Erstellen Sie einen neuen Datensatz
review_subsample_new
- Basierend auf dem Datensatzes
review_works_correct
:- Nutzen Sie die
filter()
-Funktion, um- nur englischsprachige (
language
), - Bücher und Buchkapitel (
type
) herauszufiltern.
- nur englischsprachige (
- Speichern Sie diese Umwandlung in einem neuen Datensatz mit dem Namen
review_subsample_new
- Nutzen Sie die
- Basierend auf dem Datensatzes
- Überprüfen Sie die Transformation mit Hilfe der
glimpse()
-Funktion. - ✍️ Notieren Sie, wie viele Artikel im neuen Subsample enthalten sind.
Lösung anzeigen
# Erstellung Subsample
<- review_works_correct %>%
review_subsample_new # Eingrenzung: Sprache und Typ
filter(language == "en") %>%
filter(type == "book" | type == "book-chapter")
# Überprüfung
%>% glimpse review_subsample_new
Rows: 2,994
Columns: 41
$ id <chr> "https://openalex.org/W2899962821", "https…
$ title <chr> "Introduction to systematic reviews", "Cha…
$ display_name <chr> "Introduction to systematic reviews", "Cha…
$ author <list> [<data.frame[2 x 12]>], NA, [<data.frame[…
$ ab <chr> "A systematic review is a vital part of th…
$ publication_date <chr> "2018-10-01", "2020-01-01", "2019-01-01", …
$ relevance_score <dbl> 300.1405, 255.6323, 248.6059, 231.0026, 22…
$ so <chr> "Manchester University Press eBooks", "JBI…
$ so_id <chr> "https://openalex.org/S4306463591", "https…
$ host_organization <chr> "Winchester University Press", NA, NA, NA,…
$ issn_l <chr> NA, NA, NA, NA, "0302-9743", NA, NA, NA, N…
$ url <chr> "https://doi.org/10.7765/9781526136527.000…
$ pdf_url <chr> "https://www.manchesteropenhive.com/downlo…
$ license <chr> "cc-by-nc-nd", NA, NA, NA, NA, NA, NA, "cc…
$ version <chr> "publishedVersion", "publishedVersion", "p…
$ first_page <chr> NA, NA, NA, NA, "214", "48", NA, "3", "85"…
$ last_page <chr> NA, NA, NA, NA, "227", "78", NA, "22", "94…
$ volume <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ issue <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ is_oa <lgl> TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRU…
$ is_oa_anywhere <lgl> TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRU…
$ oa_status <chr> "hybrid", "bronze", "bronze", "closed", "c…
$ oa_url <chr> "https://www.manchesteropenhive.com/downlo…
$ any_repository_has_fulltext <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, …
$ language <chr> "en", "en", "en", "en", "en", "en", "en", …
$ grants <list> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ cited_by_count <int> 423, 496, 421, 547, 274, 64, 247, 189, 136…
$ counts_by_year <list> [<data.frame[8 x 2]>], [<data.frame[6 x 2…
$ publication_year <int> 2018, 2020, 2019, 2013, 2014, 2015, 2020, …
$ cited_by_api_url <chr> "https://api.openalex.org/works?filter=cit…
$ ids <list> <"https://openalex.org/W2899962821", "htt…
$ doi <chr> "https://doi.org/10.7765/9781526136527.000…
$ type <chr> "book-chapter", "book-chapter", "book-chap…
$ referenced_works <list> NA, NA, NA, <"https://openalex.org/W11488…
$ related_works <list> <"https://openalex.org/W4385987771", "htt…
$ is_paratext <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, …
$ is_retracted <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, …
$ concepts <list> [<data.frame[16 x 5]>], [<data.frame[7 x …
$ topics <list> [<tbl_df[4 x 5]>], [<tbl_df[4 x 5]>], [<t…
$ publication_year_fct <fct> 2018, 2020, 2019, 2013, 2014, 2015, 2020, …
$ type_fct <fct> book-chapter, book-chapter, book-chapter, …
Lösung anzeigen
# Notiz:
# Subsample enthält 2994 Einträge
📋 Exercise 2: Umwandlung zu ‘tidy text’
- Erstellen Sie einen neuen Datensatz
subsample_new_tidy
,- Basierend auf dem Datensatz
review_subsample_new
, mit folgenden Schritten:- Tokenisierung der Abstracts (
ab
) mit der Funktionunnest_tokens
. - Ausschluss von Stoppwörter mit
filter
undstopwords$words
heraus. - Speichern Sie diese Umwandlung, indem Sie einen neuen Datensatz mit dem Namen
subsample_new_tidy
erstellen.
- Tokenisierung der Abstracts (
- Basierend auf dem Datensatz
- Prüfen Sie, ob die Umwandlung erfolgreich war (z.B. mit der Funktion
glimpse()
) - ✍️ Notieren Sie, wie viele Token im neuen Datensatz
subsample_new_tidy
enthalten sind.
Lösung anzeigen
# Erstellung des neuen Datensatzes `subsample_new_tidy`
<- review_subsample_new %>%
subsample_new_tidy ::unnest_tokens("text", ab) %>%
tidytextfilter(!text %in% tidytext::stop_words$word)
# Überprüfung
%>% print() subsample_new_tidy
# A tibble: 182,776 × 41
id title display_name author publication_date relevance_score so so_id
<chr> <chr> <chr> <list> <chr> <dbl> <chr> <chr>
1 https… Intr… Introductio… <df> 2018-10-01 300. Manc… http…
2 https… Intr… Introductio… <df> 2018-10-01 300. Manc… http…
3 https… Intr… Introductio… <df> 2018-10-01 300. Manc… http…
4 https… Intr… Introductio… <df> 2018-10-01 300. Manc… http…
5 https… Intr… Introductio… <df> 2018-10-01 300. Manc… http…
6 https… Intr… Introductio… <df> 2018-10-01 300. Manc… http…
7 https… Intr… Introductio… <df> 2018-10-01 300. Manc… http…
8 https… Intr… Introductio… <df> 2018-10-01 300. Manc… http…
9 https… Intr… Introductio… <df> 2018-10-01 300. Manc… http…
10 https… Intr… Introductio… <df> 2018-10-01 300. Manc… http…
# ℹ 182,766 more rows
# ℹ 33 more variables: host_organization <chr>, issn_l <chr>, url <chr>,
# pdf_url <chr>, license <chr>, version <chr>, first_page <chr>,
# last_page <chr>, volume <chr>, issue <chr>, is_oa <lgl>,
# is_oa_anywhere <lgl>, oa_status <chr>, oa_url <chr>,
# any_repository_has_fulltext <lgl>, language <chr>, grants <list>,
# cited_by_count <int>, counts_by_year <list>, publication_year <int>, …
Lösung anzeigen
# Notiz:
# Der neue Datensatz enthält 182776 Token.
📋 Exercise 3: Auswertung der Token
- Erstellen Sie einen neuen Datensatz
subsample_new_summarized
,- Fassen Sie auf der Grundlage des Datensatzes
subsample_new_tidy
die Häufigkeit der einzelnen Token zusammen, indem Sie die Funktioncount()
auf die Variabletext
anwenden. Verwenden Sie das Argumentsort = TRUE
, um den Datensatz nach absteigender Häufigkeit der Token zu sortieren. - Speichern Sie diese Transformation, indem Sie einen neuen Datensatz mit dem Namen
subsample_new_summarized
erstellen.
- Fassen Sie auf der Grundlage des Datensatzes
- Prüfen Sie, ob die Umwandlung erfolgreich war, indem Sie die Funktion
print()
verwenden.- Verwenden Sie das Argument
n = 50
, um die 50 wichtigsten Token anzuzeigen (nur möglich, wenn das Argumentsort = TRUE
bei der Ausführung der Funktioncount()
verwendet wurde)
- Verwenden Sie das Argument
- Verteilung der Token prüfen
- Verwenden Sie die Funktion
datawizard::describe_distribution()
, um verschiedene Verteilungsparameter des neuen Datensatzes zu überprüfen - ✍️ Notieren Sie, wie viele Token ein Abstract durchschnittlich enthält.
- Verwenden Sie die Funktion
- Optional: Ergebnisse mit einer Wortwolke überprüfen
- Basierend auf dem sortierten Datensatz
subsample_new_summarized
- Auswahl der 50 häufigsten Token mit Hilfe der Funktion
top_n()
- Erstellen Sie eine
ggplot()
-Basis mitlabel = text
undsize = n
alsaes()
und - Benutze ggwordcloud::geom_text_wordclout() um die Wortwolke zu erstellen.
- Verwenden Sie scale_size_are(), um die Skalierung der Wortwolke zu übernehmen.
- Verwenden Sie
theme_minimal()
für eine saubere Visualisierung.
- Auswahl der 50 häufigsten Token mit Hilfe der Funktion
- Basierend auf dem sortierten Datensatz
Lösung anzeigen
# Erstellung des neuen Datensatzes `subsample_new_summmarized`
<- subsample_new_tidy %>%
subsample_new_summmarized count(text, sort = TRUE)
# Preview Top 50 token
%>%
subsample_new_summmarized print(n = 50)
# A tibble: 14,959 × 2
text n
<chr> <int>
1 research 2761
2 literature 2539
3 review 2466
4 studies 1478
5 systematic 1231
6 study 1206
7 <NA> 936
8 social 903
9 analysis 881
10 chapter 851
11 data 824
12 management 788
13 based 786
14 paper 695
15 articles 686
16 learning 666
17 development 627
18 future 622
19 results 596
20 information 581
21 knowledge 572
22 reviews 545
23 education 518
24 factors 516
25 process 498
26 related 491
27 business 483
28 health 454
29 technology 452
30 findings 449
31 digital 437
32 methods 424
33 main 421
34 design 417
35 provide 410
36 field 400
37 quality 396
38 context 384
39 identify 382
40 current 380
41 performance 369
42 published 367
43 approach 356
44 identified 356
45 impact 347
46 relevant 344
47 systems 334
48 role 331
49 model 328
50 conducted 327
# ℹ 14,909 more rows
Lösung anzeigen
# Check distribution parameters
%>%
subsample_new_summmarized ::describe_distribution() datawizard
Variable | Mean | SD | IQR | Range | Skewness | Kurtosis | n | n_Missing
------------------------------------------------------------------------------------------
n | 12.22 | 57.24 | 5 | [1.00, 2761.00] | 24.32 | 925.44 | 14959 | 0
Lösung anzeigen
# Notiz:
# Ein Absatz enthält durchschnittlich 22 Token.
# Optional: Check results with a wordcloud
%>%
subsample_new_summmarized top_n(50) %>%
ggplot(aes(label = text, size = n)) +
::geom_text_wordcloud() +
ggwordcloudscale_size_area(max_size = 15) +
theme_minimal()
📋 Exercise 4: Wortbeziehungen im Fokus
4.1 Couting word pairs
- Zählen von häufigen Wortpaaren
- Zählen Sie auf der Grundlage des Datensatzes
subsample_new_tidy
Wortpaare mitwidyr::pairwise_count()
, mit den Argumentenitem = text
,feature = id
undsort = TRUE.
- Speichern Sie diese Transformation, indem Sie einen neuen Datensatz mit dem Namen
subsample_new_word_pairs
erstellen.
- Zählen Sie auf der Grundlage des Datensatzes
- Prüfen Sie, ob die Umwandlung erfolgreich war, indem Sie die Funktion
print()
verwenden.- Verwenden Sie das Argument
n = 50
, um die 50 wichtigsten Token anzuzeigen (nur möglich, wenn bei der Ausführung der Funktioncount()
das Argumentsort = TRUE
verwendet wurde)
- Verwenden Sie das Argument
Lösung anzeigen
# Couting word pairs among sections
<- subsample_new_tidy %>%
subsample_new_word_pairs ::pairwise_count(
widyritem = text,
feature = id,
sort = TRUE)
# Check
%>% print(n = 50) subsample_new_word_pairs
# A tibble: 7,286,586 × 3
item1 item2 n
<chr> <chr> <dbl>
1 literature review 1160
2 review literature 1160
3 research review 947
4 review research 947
5 literature research 915
6 research literature 915
7 review systematic 795
8 systematic review 795
9 literature systematic 642
10 systematic literature 642
11 studies review 588
12 review studies 588
13 research systematic 561
14 systematic research 561
15 study literature 555
16 literature study 555
17 study review 549
18 review study 549
19 literature studies 510
20 studies literature 510
21 studies research 508
22 research studies 508
23 study research 505
24 research study 505
25 based review 420
26 review based 420
27 future research 417
28 research future 417
29 analysis review 408
30 review analysis 408
31 literature chapter 404
32 chapter literature 404
33 paper review 394
34 review paper 394
35 future review 391
36 review future 391
37 results review 385
38 review results 385
39 literature paper 382
40 paper literature 382
41 future literature 381
42 literature future 381
43 literature analysis 379
44 analysis literature 379
45 based literature 379
46 literature based 379
47 chapter review 377
48 review chapter 377
49 studies systematic 371
50 systematic studies 371
# ℹ 7,286,536 more rows
4.2 Pairwise correlation
- Ermittlung der paarweisen Korrelation
- Basierend auf dem Datensatz
subsample_new_tidy
, - gruppieren Sie die Daten mit der Funktion
group_by()
nach der Variabletext
und - verwenden Sie
filter(n() >= X)
, um nur Token zu verwenden, die mindestens in einer bestimmte Anzahl (X
) vorkommen; Sie können fürX
einen Wert Ihrer Wahl wählen, ich würde jedoch dringend empfehlen, einX > 100
zu wählen, da die folgende Funktion sonst möglicherweise nicht in der Lage ist, die Berechnung durchzuführen. - Erstellen Sie Wortkorrelationen mit
widyr::pairwise_cor()
, mit den Argumentenitem = text
,feature = id
undsort = TRUE
. - Speichern Sie diese Transformation, indem Sie einen neuen Datensatz mit dem Namen
subsample_new_corr
erstellen.
- Basierend auf dem Datensatz
- Prüfen Sie die Paare mit der höchsten Korrelation mit der Funktion
print().
.
Lösung anzeigen
# Getting pairwise correlation
<- subsample_new_tidy %>%
subsample_new_corr group_by(text) %>%
filter(n() >= 250) %>%
pairwise_cor(text, id, sort = TRUE)
# Check pairs with highest correlation
%>% print(n = 50) subsample_new_corr
# A tibble: 8,372 × 3
item1 item2 correlation
<chr> <chr> <dbl>
1 chain supply 0.886
2 supply chain 0.886
3 literature review 0.614
4 review literature 0.614
5 review systematic 0.561
6 systematic review 0.561
7 sustainability sustainable 0.467
8 sustainable sustainability 0.467
9 research review 0.462
10 review research 0.462
11 literature research 0.446
12 research literature 0.446
13 future research 0.373
14 research future 0.373
15 media social 0.368
16 social media 0.368
17 literature systematic 0.354
18 systematic literature 0.354
19 learning education 0.330
20 education learning 0.330
21 studies review 0.330
22 review studies 0.330
23 research systematic 0.319
24 systematic research 0.319
25 study research 0.309
26 research study 0.309
27 study literature 0.307
28 literature study 0.307
29 studies research 0.306
30 research studies 0.306
31 articles published 0.297
32 published articles 0.297
33 articles systematic 0.280
34 systematic articles 0.280
35 models model 0.280
36 model models 0.280
37 study review 0.279
38 review study 0.279
39 results review 0.278
40 review results 0.278
41 results systematic 0.272
42 systematic results 0.272
43 based review 0.269
44 review based 0.269
45 articles review 0.268
46 review articles 0.268
47 studies systematic 0.266
48 systematic studies 0.266
49 theory theoretical 0.266
50 theoretical theory 0.266
# ℹ 8,322 more rows
📋 Exercise 5: Inhaltlicher Vergleich
- Vergleichen Sie die Ergebnisse der Übung mit den Auswertungen der Folien:
- Wie unterscheiden sich die Ergebnisse?
- Würden Sie die Bücher bzw. Buchabschnitte mit in die Untersuchung integrieren?
References
Aria, Massimo, Trang Le, Corrado Cuccurullo, Alessandra Belfiore, and June Choe. 2024. “openalexR: An R-Tool for Collecting Bibliometric Data from OpenAlex.” The R Journal 15 (4): 167–80. https://doi.org/10.32614/rj-2023-089.