FACTOR ANALYSIS

with frequencies normed by 100 and minimum text length of 100 words

Features used in the factor analysis: 1. adja: attributive adjective, 2. adjd: predicative adjective, 3. adv: adverb, 4. artdef: definite article, 5. artdem: demonstrative article, 6. artindef: indefinite article, 7. artinter: interrogative article, 8. artposs: possessive article, 9. attindef: attributive indefinita, 10. awl: average word length, 11. dass: conjunction dass/that, 12. diskmark: discourse marker, 13. eignam: proper name, 14. gen:gentive, 15. gespptk: conversational particle, 16. kaus: causal clause, 17. kokom: comparative clause, 18. kokonj: coordinating conjunction, 19. kommv: verb of communication, 20. kond: conditional clause, 21. nabs: abstract noun, 22. nebfin: subordinating with finite verb, 23. nebzuinf: subordinating with zu infinitive, 24. noml: nominalization, 25. nreg: regular noun, 26. pass: passive, 27. pdem: demonstrative pronoun, 28. pindef: indefinite pronoun, 29. pinter: interrogative pronoun, 30. pper1: 1st person pronoun, 31. pper2: 2nd person pronoun, 32. pper3: 3rd person pronoun, 33. pposs: possessive pronoun, 34. prefl: reflexive pronoun, 35. prel: relative pronoun, 36. prep: preposition, 37. proadv: pronominal adverb, 38. ptkifg: intensity particle, 39. ptkma: modal particle, 40. ptkneg: negation particle, 41. qutag: question tag, 42. temp: temporal clause, 43. ttr: Type-token-ratio, 44. v2s: verb 2nd subordinate clause, 45. vfut: future, 46. vimp: imperative, 47. vinfzu: Zu Infinitive object clause, 48. vipast: indicative past, 49. vipres: indicative present, 50. vmod: modal verb, 51. vperf: Perfekt, 52. vpqp: Past perfect simple, 53. vspast: subjunctive past, 54. vspres: subjjunctive present, 55. vvipres: full verb indicative present

library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.4.4     ✔ tibble    3.2.1
## ✔ lubridate 1.9.3     ✔ tidyr     1.3.1
## ✔ purrr     1.0.2     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(performance)
library(psych)
## 
## Attaching package: 'psych'
## 
## The following objects are masked from 'package:ggplot2':
## 
##     %+%, alpha
library(ggcorrplot)
# Load the data
features_count_normed_100 <- read_csv("features_extraction/features_count_normed_100.csv")
## Rows: 3068 Columns: 56
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr  (1): doc_id
## dbl (55): awl, ttr, pindef, pposs, prefl, pdem, pinter, prel, artdef, artind...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Put the column ‘register’ after ‘doc_id’

features_count_normed_100 <- features_count_normed_100 %>%
  select(doc_id, awl:eignam)

Get the indices for the correlation matrix

indices_100 <- features_count_normed_100 %>%
  select(-doc_id)

Add the column register to tha data

features_count_normed_100$register <- gsub("\\d+", "", features_count_normed_100$doc_id)
features_count_normed_100 <- features_count_normed_100 %>% 
  mutate(register = recode(register, ag = "everyday conversation", agw = "academic article humanities", 
                           bk = "business communication", bl = "blog", bt = "fiction literature", 
                           bz = "package insert", df = "documentary", dgw = "dissertation humanities",
                           dinw = "dissertation ing. nat. sci.",  dlw = "dissertation life sciences",
                           essay = "essay", ev = "expert lecture", fd = "movie drama", fs = "tv series",
                           ga = "instruction manual", gn = "spoken news", gt = "legal texts", 
                           hk = "horoscope", ik = "institutional communication", int = "interview", 
                           jl = "young literature", km = "comedy", ks = "crime series", la = "editorial",
                           lb = "letter to the editor", ld = "song lyrics", lk = "readers comment", 
                           ma = "magazine article", md = "news", mn = "opinion", pc = "professional chat",
                           pd = "sermon", pg = "oral exam", pinw = "popular science articles ing nat sci",
                           plw = "popular science articles life sci", pp = "plenary minutes", 
                           pr = "political speech", rz = "recipe", sa = "job offer", 
                           sb = "non-fiction book", sv = "student lecture", th = "theatre play", 
                           tt = "ted talk", vl = "lectures", wa = "wikipedia article", 
                           wd = "wikipedia talk", wlbgw = "scientific textbook humanities", 
                           wlbinw = "scientif textbook Ing. nat. sci", 
                           wlblw = "scientific textbook life sci", ws = "website", 
                           za = "newspaper article", zi = "newspaper interview"))

1. Evaluate the data

  1. Correlation Matrix
cor_matrix <- cor(indices_100) %>%
  data.frame() %>%
  rownames_to_column()

# Remove overcorrelated features > 0.7
write.csv(cor(indices_100)>0.7, file="factor_analysis/suspect_correlations.csv")
overcorrelated <- c("pdem", "dass", "vpqp", "gen", "vvipres", "ptkma")
indices_100 <- indices_100[ ,!(names(indices_100) %in% overcorrelated)]
write.csv(indices_100, "factor_analysis/indices_100.csv")

# Visualize the correlation matrix
cor_matrix <- round(cor(indices_100), 2)
  1. Bartellt’s Test of Sphericity
r <- cor(indices_100)
check_sphericity_bartlett(r, n = nrow(indices_100))
## # Test of Sphericity
## 
## Bartlett's test of sphericity suggests that there is sufficient significant correlation in the data for factor analysis (Chisq(1176) = 71811.22, p < .001).
cortest.bartlett(indices_100)
## R was not square, finding R from data
## $chisq
## [1] 71811.22
## 
## $p.value
## [1] 0
## 
## $df
## [1] 1176
  1. KMO
check_kmo(r, n = nrow(indices_100))
## # KMO Measure of Sampling Adequacy
## 
## The Kaiser, Meyer, Olkin (KMO) overall measure of sampling adequacy suggests that data seems appropriate for factor analysis (KMO = 0.87). The individual KMO scores are: awl (0.72), ttr (0.66), pindef (0.96), pposs (0.72), prefl (0.81), pinter (0.96), prel (0.86), artdef (0.90), artindef (0.80), attindef (0.85), artposs (0.77), artdem (0.85), artinter (0.70), vmod (0.92), kommv (0.93), prep (0.92), kokonj (0.64), vinfzu (0.79), nebfin (0.80), kond (0.80), kaus (0.69), temp (0.51), nebzuinf (0.72), kokom (0.81), vipres (0.80), vipast (0.40*), vspres (0.65), vspast (0.90), vimp (0.85), vfut (0.81), pass (0.78), vperf (0.86), proadv (0.74), adv (0.95), pper1 (0.92), pper2 (0.87), pper3 (0.50), adja (0.96), adjd (0.93), v2s (0.74), nabs (0.81), noml (0.92), nreg (0.93), ptkneg (0.97), gespptk (0.89), ptkifg (0.94), diskmark (0.86), qutag (0.91), eignam (0.72).
KMO(indices_100)
## Kaiser-Meyer-Olkin factor adequacy
## Call: KMO(r = indices_100)
## Overall MSA =  0.87
## MSA for each item = 
##      awl      ttr   pindef    pposs    prefl   pinter     prel   artdef 
##     0.72     0.66     0.96     0.72     0.81     0.96     0.86     0.90 
## artindef attindef  artposs   artdem artinter     vmod    kommv     prep 
##     0.80     0.85     0.77     0.85     0.70     0.92     0.93     0.92 
##   kokonj   vinfzu   nebfin     kond     kaus     temp nebzuinf    kokom 
##     0.64     0.79     0.80     0.80     0.69     0.51     0.72     0.81 
##   vipres   vipast   vspres   vspast     vimp     vfut     pass    vperf 
##     0.80     0.40     0.65     0.90     0.85     0.81     0.78     0.86 
##   proadv      adv    pper1    pper2    pper3     adja     adjd      v2s 
##     0.74     0.95     0.92     0.87     0.50     0.96     0.93     0.74 
##     nabs     noml     nreg   ptkneg  gespptk   ptkifg diskmark    qutag 
##     0.81     0.92     0.93     0.97     0.89     0.94     0.86     0.91 
##   eignam 
##     0.72

2. Determine number of factors

Scree plot

scree(indices_100, pc = FALSE)

Parallel Analysis (Parallel analysis suggests that the number of factors = 12)

fa.parallel(indices_100, fa="fa")

## Parallel analysis suggests that the number of factors =  12  and the number of components =  NA

Get eigenvalues

ev <- eigen(cor(indices_100))
ev$values
##  [1] 10.8390622  4.0320761  2.6974669  2.1463225  1.8329937  1.4916142
##  [7]  1.4688990  1.3047009  1.2260808  1.1480259  1.1136819  1.0504540
## [13]  1.0161183  0.9543365  0.9325872  0.8700500  0.8358260  0.8195085
## [19]  0.7667178  0.7412144  0.7046914  0.6864539  0.6633438  0.6608061
## [25]  0.6303353  0.5939525  0.5757835  0.5665558  0.5276989  0.4930476
## [31]  0.4773794  0.4534827  0.4407766  0.4217900  0.4006770  0.3738711
## [37]  0.3567733  0.3527625  0.3228193  0.2932031  0.2699016  0.2634757
## [43]  0.2376521  0.2209981  0.1962426  0.1700112  0.1542033  0.1300776
## [49]  0.0734971

3. Extract and rotate the factors

Solution with 5 factors

fa_5 <- fa(indices_100, fm = "pa", nfactors = 5, rotate = "promax")
## Loading required namespace: GPArotation
print(fa_5, cut = 0)
## Factor Analysis using method =  pa
## Call: fa(r = indices_100, nfactors = 5, rotate = "promax", fm = "pa")
## Standardized loadings (pattern matrix) based upon correlation matrix
##            PA1   PA4   PA2   PA5   PA3    h2   u2 com
## awl      -0.33 -0.09 -0.13  0.15 -0.04 0.227 0.77 2.0
## ttr       0.10 -0.05 -0.01  0.30  0.05 0.083 0.92 1.3
## pindef    0.60  0.18  0.12 -0.09  0.00 0.559 0.44 1.3
## pposs     0.07  0.01 -0.02 -0.06 -0.01 0.014 0.99 2.2
## prefl     0.08  0.00  0.58 -0.16  0.07 0.354 0.65 1.2
## pinter    0.25  0.43 -0.12 -0.12  0.10 0.469 0.53 2.1
## prel     -0.10 -0.06  0.60  0.01  0.13 0.415 0.59 1.2
## artdef   -0.32 -0.16  0.14  0.49  0.22 0.587 0.41 2.7
## artindef -0.05 -0.13  0.25  0.24  0.15 0.199 0.80 3.2
## attindef  0.06  0.17  0.31 -0.01  0.02 0.153 0.85 1.6
## artposs  -0.23  0.27  0.32 -0.52 -0.01 0.385 0.62 2.7
## artdem    0.14  0.01  0.39  0.29 -0.03 0.267 0.73 2.2
## artinter  0.07  0.17  0.17  0.16 -0.13 0.104 0.90 4.2
## vmod      0.27  0.52  0.11  0.14  0.06 0.487 0.51 1.8
## kommv     0.41  0.22  0.00 -0.09  0.36 0.579 0.42 2.6
## prep     -0.60 -0.18  0.13  0.23  0.12 0.674 0.33 1.7
## kokonj   -0.09 -0.17  0.04 -0.33 -0.57 0.389 0.61 1.9
## vinfzu   -0.11  0.14  0.65 -0.02 -0.07 0.448 0.55 1.2
## nebfin    0.52  0.17  0.43  0.03 -0.09 0.554 0.45 2.3
## kond      0.20  0.49  0.14  0.00 -0.18 0.390 0.61 1.8
## kaus      0.48 -0.05  0.10  0.12 -0.12 0.201 0.80 1.4
## temp      0.06 -0.25  0.29 -0.36  0.07 0.197 0.80 2.9
## nebzuinf -0.09  0.02  0.41 -0.06 -0.06 0.165 0.83 1.2
## kokom     0.08  0.08  0.24 -0.09  0.06 0.102 0.90 2.0
## vipres    0.23  0.79 -0.06  0.07 -0.17 0.808 0.19 1.3
## vipast    0.16 -0.55  0.32 -0.31  0.44 0.551 0.45 3.4
## vspres    0.00 -0.05 -0.01  0.03  0.43 0.178 0.82 1.0
## vspast    0.42  0.08  0.20  0.04  0.21 0.337 0.66 2.1
## vimp      0.02  0.41 -0.31 -0.26  0.13 0.442 0.56 2.9
## vfut     -0.08  0.29  0.07 -0.01  0.02 0.080 0.92 1.3
## pass     -0.10  0.06  0.01  0.35 -0.01 0.146 0.85 1.2
## vperf     0.16  0.30  0.04  0.14  0.19 0.213 0.79 2.8
## proadv    0.08 -0.04  0.33  0.07 -0.13 0.129 0.87 1.5
## adv       0.75  0.09 -0.08 -0.01  0.05 0.674 0.33 1.1
## pper1     0.30  0.38 -0.09 -0.36  0.09 0.681 0.32 3.1
## pper2     0.05  0.50 -0.23 -0.28  0.06 0.511 0.49 2.1
## pper3    -0.09  0.27  0.09 -0.11 -0.20 0.100 0.90 2.7
## adja     -0.45 -0.22  0.16  0.29 -0.09 0.630 0.37 2.7
## adjd      0.74 -0.08  0.00 -0.15 -0.23 0.564 0.44 1.3
## v2s      -0.09  0.10 -0.03 -0.17  0.45 0.275 0.73 1.5
## nabs     -0.30  0.12  0.34  0.26  0.01 0.332 0.67 3.2
## noml     -0.45  0.20  0.13  0.22  0.20 0.288 0.71 2.5
## nreg     -0.61 -0.24 -0.15 -0.01 -0.25 0.726 0.27 1.8
## ptkneg    0.30  0.47  0.10 -0.07  0.10 0.548 0.45 2.0
## gespptk   0.76  0.01 -0.41  0.21  0.04 0.683 0.32 1.7
## ptkifg    0.78  0.00  0.20  0.08 -0.02 0.601 0.40 1.1
## diskmark  0.85 -0.20 -0.09  0.29 -0.13 0.552 0.45 1.4
## qutag     0.45  0.03 -0.30  0.11  0.09 0.294 0.71 2.0
## eignam   -0.30 -0.10 -0.08  0.02  0.55 0.353 0.65 1.7
## 
##                        PA1  PA4  PA2  PA5  PA3
## SS loadings           7.26 4.05 3.13 2.30 1.95
## Proportion Var        0.15 0.08 0.06 0.05 0.04
## Cumulative Var        0.15 0.23 0.29 0.34 0.38
## Proportion Explained  0.39 0.22 0.17 0.12 0.10
## Cumulative Proportion 0.39 0.61 0.77 0.90 1.00
## 
##  With factor correlations of 
##       PA1   PA4   PA2   PA5   PA3
## PA1  1.00  0.52 -0.04 -0.32  0.17
## PA4  0.52  1.00  0.09 -0.26  0.15
## PA2 -0.04  0.09  1.00  0.21  0.15
## PA5 -0.32 -0.26  0.21  1.00 -0.23
## PA3  0.17  0.15  0.15 -0.23  1.00
## 
## Mean item complexity =  2
## Test of the hypothesis that 5 factors are sufficient.
## 
## df null model =  1176  with the objective function =  23.55 with Chi Square =  71811.22
## df of  the model are 941  and the objective function was  6.34 
## 
## The root mean square of the residuals (RMSR) is  0.04 
## The df corrected root mean square of the residuals is  0.05 
## 
## The harmonic n.obs is  3068 with the empirical chi square  12757.92  with prob <  0 
## The total n.obs was  3068  with Likelihood Chi Square =  19318.09  with prob <  0 
## 
## Tucker Lewis Index of factoring reliability =  0.674
## RMSEA index =  0.08  and the 90 % confidence intervals are  0.079 0.081
## BIC =  11763
## Fit based upon off diagonal values = 0.97
## Measures of factor score adequacy             
##                                                    PA1  PA4  PA2  PA5  PA3
## Correlation of (regression) scores with factors   0.97 0.95 0.92 0.90 0.89
## Multiple R square of scores with factors          0.94 0.91 0.85 0.81 0.79
## Minimum correlation of possible factor scores     0.88 0.82 0.70 0.62 0.58

Factorial composition for a 5 solution

FACTOR 1

positive pole: diskmark 0.85, ptkifg 0.78, gespptk 0.76, adv 0.75, adjd 0.74, pindef 0.60, nebfin 0.52, kaus 0.48, qutag 0.45, vspast 0.42, kommv 0.41, ptkneg 0.30, pper1 0.30

negative pole: nreg -0.61, prep -0.60, adja -0.45, noml -0.45, awl -0.33, artdef -0.32, nabs -0.30, eignam -0.30

FACTOR 2

positive pole: vipres 0.79, vmod 0.52, pper2 0.50, kond 0.49, ptkneg 0.47, pinter 0.43, vimp 0.41, pper1 0.38, vperf 0.30

negative pole: vipast -0.55

FACTOR 3

positive pole: vinfzu 0.65, prel 0.60, prefl 0.58, nebfin 0.43, nebzuinf 0.41, artdem 0.39, nabs 0.34, proadv 0.33, artposs 0.32, vipast 0.32, attindef 0.31

negative pole: vimp -0.31, qutag -0.30

FACTOR 4

positive pole: artdef 0.49, pass 0.35, ttr 0.30

negative pole: artposs -0.52, temp -0.36, pper1 -0.36, kokonj -0.33, vipast -0.31

FACTOR 5

positive pole: eignam 0.55, v2s 0.45, vipast 0.44, vspres 0.43, kommv 0.36

4. Compute z-scores

z-scores for each text

df_std_100 <- features_count_normed_100 %>%
  select(awl:eignam)

z_scores_100 <- sapply(df_std_100, function(df_std_100) (df_std_100 - mean(df_std_100))/sd(df_std_100))
z_scores_df_100 <- as.data.frame(z_scores_100)
z_scores_df_100<- z_scores_df_100 %>%
  cbind(doc_id=features_count_normed_100$doc_id,
        register=features_count_normed_100$register)

z-scores per register

Extract the prefixs of doc_id and save them in the new column register_id

z_scores_df_100$register_id <- gsub("\\d+", "", z_scores_df_100$doc_id)

z_scores_reg_100 <- z_scores_df_100 %>%
  group_by(register_id) %>%
  select(awl:eignam) %>%
  summarise_all(sum)
## Adding missing grouping variables: `register_id`
register <- c('everyday conversation', 'academic article humanities', 'business communication', 
              'blog', 'fiction literature', 'package insert', 'documentary', 'dissertation humanities', 
              'dissertation ing. nat. sci.', 'dissertation life sciences', 'essay', 'expert lecture', 
              'movie drama', 'tv series', 'instruction manual', 'spoken news', 'legal texts',
              'horoscope', 'institutional communication', 'interview', 'young literature', 'comedy',
              'crime series', 'editorial', 'letter to the editor', 'song lyrics', 'readers comment',
              'magazine article', 'news', 'opinion', 'professional chat', 'sermon', 'oral exam', 
              'popular science articles ing. nat. sci.', 'popular science articles life sci', 
              'plenary minutes', 'political speech', 'recipe', 'job offer', 'non-fiction book', 
              'student lecture', 'theatre play', 'ted talk', 'lectures', 'wikipedia article', 
              'wikipedia talk', 'scientific textbook humanities', 'scientif textbook Ing. nat. sci', 
              'scientific textbook life sci', 'website', 'newspaper article', 'newspaper interview')
z_scores_reg_100$register <- register

# Reorder the columns
z_scores_reg_100 <- z_scores_reg_100 %>%
  select(register_id, register, everything())

5. Compute factor scores

Select the variables of each factor with z-scores

f1_100 <- z_scores_df_100[c("doc_id", "register", "awl", "prep", "adja", "noml", "nreg", 
                            "pindef", "kommv", "kaus", "vspast", "adv", "adjd", "gespptk", 
                            "ptkifg", "diskmark", "qutag", "nebfin")]
f2_100 <- z_scores_df_100[c("doc_id", "register", "pinter", "vmod", "nebfin", "kond", "vipres", 
                            "vimp", "vperf", "pper1", "pper2", "ptkneg", "vipast")]
f3_100 <- z_scores_df_100[c("doc_id", "register", "prefl", "prel", "attindef", "artdem", "vinfzu", 
                            "nebzuinf", "proadv", "nabs")]
f4_100 <- z_scores_df_100[c("doc_id", "register", "ttr", "artdef", "pass", "artposs", "temp", "kokonj")]
f5_100 <- z_scores_df_100[c("doc_id", "register", "vspres", "v2s", "eignam")]

Add the positive loadinsg-features and subtract the negative-loading features on each dimension. (Features that loaded in many dimensions where only used to compute the scores for the dimension with higher loading)

df_scores_100 <- z_scores_df_100 %>%
  group_by(doc_id) %>%
  mutate(f1_score_100 = sum(c(pindef, kommv, kaus, vspast, adv, adjd, gespptk, ptkifg, diskmark, qutag,
                              nebfin)) - sum(c(awl, prep, adja, noml, nreg)),
         f2_score_100 = sum(c(pinter, vmod, nebfin, kond, vipres, vimp, vperf, pper1, pper2, ptkneg)) -
           vipast,
         f3_score_100 = sum(c(prefl, prel, attindef, artdem, vinfzu, nebzuinf, proadv, nabs)),
         f4_score_100 = sum(c(ttr, artdef, pass)) - sum(c(artposs, temp, kokonj)),
         f5_score_100 = sum(c(vspres, v2s, eignam))
  )
df_scores_100 %>%
  select(register_id:f5_score_100)
## Adding missing grouping variables: `doc_id`
## # A tibble: 3,068 × 7
## # Groups:   doc_id [3,068]
##    doc_id register_id f1_score_100 f2_score_100 f3_score_100 f4_score_100
##    <chr>  <chr>              <dbl>        <dbl>        <dbl>        <dbl>
##  1 ag001  ag                  20.0         5.65        -6.04      1.07   
##  2 ag002  ag                  28.3        10.9         -7.57      0.154  
##  3 ag003  ag                  18.4         8.12        -8.06      5.56   
##  4 ag004  ag                  19.3         6.62        -7.48      1.29   
##  5 ag005  ag                  25.6        10.5         -6.84     -0.0117 
##  6 ag006  ag                  24.2         9.15        -7.18      2.87   
##  7 ag007  ag                  26.4        11.0         -4.23      0.701  
##  8 ag008  ag                  17.9         7.62        -5.41      0.544  
##  9 ag009  ag                  20.0         9.96        -3.10     -0.247  
## 10 ag010  ag                  32.7         8.01        -5.56     -0.00374
## # ℹ 3,058 more rows
## # ℹ 1 more variable: f5_score_100 <dbl>

Count total number of texts per registers

text_count_reg_100 <- df_scores_100 %>%
  group_by(register_id) %>%
  summarize(count = n()) %>%
  rename(text_count = count)
# Add column register from df_scores to text_count_register
text_count_reg_100$register <- register

Reorder columns

text_count_reg_100 <- text_count_reg_100 %>%
  select(register_id, register, text_count)

print(text_count_reg_100)
## # A tibble: 52 × 3
##    register_id register                    text_count
##    <chr>       <chr>                            <int>
##  1 ag          everyday conversation               50
##  2 agw         academic article humanities         50
##  3 bk          business communication              50
##  4 bl          blog                               100
##  5 bt          fiction literature                  75
##  6 bz          package insert                      50
##  7 df          documentary                         50
##  8 dgw         dissertation humanities             50
##  9 dinw        dissertation ing. nat. sci.         50
## 10 dlw         dissertation life sciences          50
## # ℹ 42 more rows

6. Mean dimensions scores

Computer mean dimension scores = factor_score / total texts of register Compute total factor scores for each register

df_scores2 <- df_scores_100 %>%
  group_by(register_id) %>%
  summarise(f1_score_total = sum(f1_score_100, na.rm=TRUE),
            f2_score_total = sum(f2_score_100, na.rm=TRUE),
            f3_score_total = sum(f3_score_100, na.rm=TRUE),
            f4_score_total = sum(f4_score_100, na.rm=TRUE),
            f5_score_total = sum(f5_score_100, na.rm=TRUE))

mean_ds_100 <- data_frame()
## Warning: `data_frame()` was deprecated in tibble 1.1.0.
## ℹ Please use `tibble()` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
mean_ds_100 <- full_join(text_count_reg_100, df_scores2, by = "register_id")

Compute mean dimension scores

mean_ds_100 <- mean_ds_100 %>%
  group_by(register_id) %>%
  mutate(mean_ds1 = f1_score_total/text_count,
         mean_ds2 = f2_score_total/text_count,
         mean_ds3 = f3_score_total/text_count,
         mean_ds4 = f4_score_total/text_count,
         mean_ds5 = f5_score_total/text_count)

mean_ds_100 %>%
  select(register_id, register, mean_ds1:mean_ds5)
## # A tibble: 52 × 7
## # Groups:   register_id [52]
##    register_id register             mean_ds1 mean_ds2 mean_ds3 mean_ds4 mean_ds5
##    <chr>       <chr>                   <dbl>    <dbl>    <dbl>    <dbl>    <dbl>
##  1 ag          everyday conversati…    26.4      7.77   -5.69     0.517  -0.943 
##  2 agw         academic article hu…    -6.45    -4.29    3.34     3.03   -0.806 
##  3 bk          business communicat…   -10.4     -3.98    0.908    0.666  -1.22  
##  4 bl          blog                     1.21     2.01    3.62    -1.43    0.0985
##  5 bt          fiction literature       3.85    -2.93    0.629   -2.75    1.12  
##  6 bz          package insert          -8.04     3.35   -2.59     0.605  -1.04  
##  7 df          documentary              8.49     6.03   -0.586   -0.648   0.181 
##  8 dgw         dissertation humani…    -6.01    -4.06    3.10     8.96   -0.588 
##  9 dinw        dissertation ing. n…    -8.02    -4.92    1.81     9.39   -1.45  
## 10 dlw         dissertation life s…    -9.62    -7.12   -0.942    6.19   -1.17  
## # ℹ 42 more rows