Warning, /sdk/pology/lang/nn/exclusion/lag-paradigme-oversikt.R is written in an unsupported language. File is not indexed.

0001 #!/usr/bin/Rscript --vanilla
0002 #
0003 # Lag oversikt over kva kombinasjonar av bøyingar
0004 # som eksisterer i Norsk ordbank.
0005 #
0006 # For kvar kombinasjon vel me éi føretrekt bøying,
0007 # dersom dette gjev meining (det gjer det for eksempel
0008 # ikkje for ord som berre har valfritt kjønn).
0009 #
0010 # Brukar òg ordfrekvensinformasjon frå KDE-omsettinga,
0011 # for å få betre ordeksempel (funkar ikkje perfekt,
0012 # men er nyttig).
0013 
0014 
0015 # Innstillingar og filinnlesing -------------------------------------------
0016 
0017 # Ymse pakkar for datahandsaming
0018 library(tidyverse)
0019 
0020 # Mappe som inneheld filene til Norsk ordbank
0021 # og frekvensinformasjon frå KDE-omsettinga
0022 mappe_ordbank = "~/utvikling/ordbanken"
0023 mappe_frek = "~/utvikling/kde/trunk/l10n-support/nn/skript/frekvensoversikt"
0024 
0025 # Les ordbankfiler og fjern unødvendige kolonnar
0026 les_fil = function(filnamn, ...) {
0027   d = read_tsv(paste0(mappe_ordbank, "/", filnamn), ...)
0028   d
0029 }
0030 
0031 # Les inn alle datafilene
0032 d_lemma = les_fil(
0033   "lemma_nn.txt",
0034   col_types = cols_only(LEMMA_ID = col_integer(), GRUNNFORM = col_character()))
0035 d_fullform = les_fil(
0036   "fullformsliste_nn.txt",
0037   col_types = cols_only(
0038     LEMMA_ID = col_integer(),
0039     OPPSLAG = col_character(),
0040     TAG = col_character(),
0041     PARADIGME_ID = col_character(),
0042     BOY_NUMMER = col_integer(),
0043     FRADATO = col_character(),
0044     TILDATO = col_character(),
0045     NORMERING = col_character()
0046   )
0047 )
0048 d_lemmaparadigme = les_fil(
0049   "lemma_paradigme_nn.txt",
0050   col_types = cols_only(
0051     LEMMA_ID = col_integer(),
0052     PARADIGME_ID = col_character(),
0053     NORMERING = col_character(),
0054     FRADATO = col_character(),
0055     TILDATO = col_character(),
0056     KOMMENTAR = col_character()
0057   )
0058 )
0059 d_paradigme = les_fil(
0060   "paradigme_boying_nn.txt",
0061   col_types = cols_only(
0062     PARADIGME_ID = col_character(),
0063     BOY_NUMMER = col_integer(),
0064     BOY_GRUPPE = col_character(),
0065     BOY_UTTRYKK = col_character()
0066   )
0067 )
0068 d_frek = read_table(paste0(mappe_frek, "/", "frekvens-nn.dat"),
0069                     col_names = c("frek", "OPPSLAG"), col_types = "nc")
0070 
0071 
0072 
0073 # Lag paradigmeoversikt ---------------------------------------------------
0074 
0075 # Legg til bruksfrekvensinfo for kvar fullform,
0076 # og oppsummer til slutt på lemmanivå
0077 # (vil vera misvisande for homograf, men ikkje noko stort problem)
0078 d_ffrek = d_fullform %>% 
0079   select(LEMMA_ID, OPPSLAG) %>% 
0080   distinct %>% # Vil ikkje telja frekvensinfo for duplikatbøyingar fleire gongar
0081   left_join(d_frek, by="OPPSLAG")
0082 d_lfrek = d_ffrek %>% 
0083   group_by(LEMMA_ID) %>% 
0084   summarise(frek = sum(frek, na.rm = TRUE), .groups = "drop") %>% 
0085   left_join(d_lemma, by = "LEMMA_ID")
0086 
0087 # d_lemmaparadigme skal i utgangspunktet innehalda alle
0088 # bøyingsparadigma til dei ulike lemmaa (gjer det ikkje heilt,
0089 # men det er vel ein feil som skal rettast?), så me
0090 # brukar denne for å finna paradigmekomboar
0091 
0092 # Paradigma står i vilkårleg rekkjefølgje innanfor lemma,
0093 # så me vil sjå vekk frå rekkjefølgja
0094 d_lp = d_lemmaparadigme %>% 
0095   arrange(LEMMA_ID, PARADIGME_ID)
0096 
0097 # Samandrag over paradigme for kvart lemma
0098 d_psam_alle = d_lp %>% 
0099   group_by(LEMMA_ID) %>% 
0100   summarise(par_tekst = str_c(PARADIGME_ID, collapse=","),
0101             n_par = n(), .groups = "drop")
0102 
0103 # Sjå berre på tilfelle der me har valfridom i bøying
0104 d_psam = d_psam_alle %>% 
0105   filter(n_par > 1)
0106 
0107 # Legg til frekvensinfo og hent ut
0108 # det mest frekvente lemmaet for
0109 # kvar paradigmekombo
0110 d_psam_pop = d_psam %>%
0111   left_join(d_lfrek, by = "LEMMA_ID") %>% 
0112   arrange(par_tekst, desc(frek)) %>% 
0113   distinct(par_tekst, .keep_all = TRUE) %>%  # Berre første/mest populære lemma
0114   arrange(desc(frek)) # Sorter paradigmekomboar etter frekvens
0115 
0116 
0117 
0118 # Oppdatering og lagring av fil -------------------------------------------
0119 
0120 # Gjer klar fil for manuell redigering
0121 # Treng berre laga oversikt for ord
0122 # som faktisk er brukte i omsettingane
0123 d_utdata = d_psam_pop %>% 
0124   filter(frek > 0) %>% 
0125   select(par_tekst, LEMMA_ID, GRUNNFORM)
0126   
0127 # Legg til ekstrakolonnar
0128 # (Brukar NA i staden for "" på grunn av seinare eksport)
0129 d_utdata$val = NA_character_       # Paradigmet me vel for denne typen ord
0130 d_utdata$kommentar = NA_character_ # Kommentar til valet/paradigmekomboen
0131 d_utdata$unntak = NA_character_    # Ev. unntak, på forma LEMMA_ID1=700,LEMMA_ID2=49G,…
0132 
0133 
0134 # Les inn gammal fil (for oppdatering)
0135 d_gammal = read_csv("paradigme-komboar.csv",
0136                                                                                 col_types = cols(par_tekst = col_character(),
0137                                                                                                                                                  LEMMA_ID = col_integer(),
0138                                                                                                                                                  GRUNNFORM = col_character(),
0139                                                                                                                                                  val = col_character(),
0140                                                                                                                                                  kommentar = col_character()
0141 ))
0142 d_nye = d_utdata %>% 
0143         anti_join(d_gammal, by = "par_tekst")
0144 d_oppdatert = bind_rows(d_gammal, d_nye)
0145 
0146 
0147 # Lagra oversiktsfil i CSV-format for manuell redigering
0148 #
0149 # Gjer det nøyaktig slik (og brukar for eksempel ikkje write_csv())
0150 # for at fila skal kunna redigerast med LibreOffice Calc utan at
0151 # det vert gjort formateringsendringar. Bruk følgjande innstillingar
0152 # ved import:
0153 #
0154 #   Skild med: Komma (ingenting anna)
0155 #   Formater sitatfelt som tekst: ja (kryssa av)
0156 #
0157 # Må etter import merkja heile «val»-kolonnen og endra «Talformat» til
0158 # «Tekst», for å hindra at talkodar som begynner med 0 mistar 0-talet.
0159 # (Det er *ikkje* nok eller nødvendig å gjera dette ved sjølve importen.)
0160 #
0161 write.csv(d_oppdatert, "paradigme-komboar.csv", row.names = FALSE, na = "")
0162 
0163 
0164 
0165 
0166 # Lag ordekskluderingsfil -------------------------------------------------
0167 
0168 # Skal så laga ei oversikt over alle orda som skal ekskluderast
0169 d = d_oppdatert
0170 
0171 # Bør først sjekka at paradigmekoden me har valt faktisk er
0172 # ein av dei gyldige paradigmekodane for lemmaet
0173 d = d %>% mutate(ok_val = is.na(val) | 
0174                                                                         str_detect(par_tekst, str_c("\\b", d$val, "\\b")))
0175 if(!all(d$ok_val)) {
0176         stop(paste0("Minst éin paradigmekombo har ugyldig paradigmekode valt:\n",
0177                                                         paste0(format(filter(d, !ok_val)), collapse="\n")))
0178 }
0179 
0180 # Unntak er litt komlisert å handtera,
0181 # men det går bra … :)
0182 
0183 # Hent ut unntaka frå ein tekststreng
0184 # og lag ein tibble med tilhøyrande info
0185 hent_unntak = function(x) {
0186   d_unntak = str_split_fixed(x, "=", 2)
0187   colnames(d_unntak) = c("LEMMA_ID", "val")
0188   as_tibble(d_unntak)
0189 }
0190 
0191 # Unntaksmønstera, med éi rad for
0192 # kvart lemma som har eit unntak
0193 d_unntaksmønster = d %>% 
0194         filter(!is.na(unntak)) %>% 
0195         select(par_tekst, unntak) %>%
0196         mutate(
0197                 unntak_liste =
0198                   str_split(unntak, ",") %>%
0199                   map(hent_unntak)) %>% 
0200         unnest(unntak_liste) %>% 
0201         mutate(LEMMA_ID = as.integer(LEMMA_ID))
0202 
0203 # Sjekk at me ikkje har fleire unntak for same lemma
0204 stopifnot(!any(duplicated(d_unntaksmønster)))
0205 
0206 # Sjekk at alle unntaka viser til LEMMA_ID-ar som
0207 # finst og at tilhøyrande PARADIGME_ID-ar òg finst
0208 # for den aktuelle LEMMA_ID-en
0209 unntak_feil = d_unntaksmønster %>% 
0210         anti_join(d_fullform, by=c("LEMMA_ID", "val"="PARADIGME_ID"))
0211 if(nrow(unntak_feil) > 0) {
0212         stop(paste0("Minst eitt unntak viser til ugyldig lemma-ID eller paradigme-ID:\n",
0213                                                         paste0(format(unntak_feil), collapse="\n")))
0214 }
0215 
0216 
0217 # Alle fullformene + info om føretrekt paradigme
0218 # for lemmaa som følgjer hovudregelen
0219 d_alle_hovudregel = d_oppdatert %>% 
0220         select(par_tekst, val) %>% 
0221         left_join(d_psam, by="par_tekst") %>% 
0222         right_join(d_fullform, by="LEMMA_ID")
0223 
0224 # Alle fullformene for unntaka + info om føretrekt paradigme
0225 d_unntak = d_unntaksmønster %>% 
0226         left_join(d_fullform, by="LEMMA_ID")
0227 
0228 # Alle fullformene, med unntak der det trengst +
0229 # info om føretrekt paradigme
0230 d_alle = d_alle_hovudregel %>% 
0231         anti_join(d_unntak, by="LEMMA_ID") %>% 
0232         bind_rows(d_unntak)
0233 
0234 # Info om ei fullform er gyldig
0235 d_alle = d_alle %>% 
0236         mutate(gyldig_form = (is.na(val) | PARADIGME_ID == val))
0237         
0238 # Fullformene som er gyldige eller ugyldige
0239 d_gyldige = d_alle %>% filter(gyldig_form)
0240 d_ugyldige = d_alle %>% filter(!gyldig_form)
0241 
0242 # Men at ei form er ugyldig er ikkje god nok
0243 # grunn til å ekskludera ho. Det kan vera det
0244 # same «ordet» òg er med blant dei gyldige
0245 # formene, anten i det utvaldet paradigmet til
0246 # lemmaet, eller for eit anna lemma (homografar).
0247 # Eksluderer derfor berre dei orda som ikkje
0248 # finst i samlinga av gyldige ord.
0249 ord_ekskluder = sort(setdiff(d_ugyldige$OPPSLAG, d_gyldige$OPPSLAG))
0250 
0251 # Lagra ekskluderingsordlista
0252 write_lines(ord_ekskluder, "feil-paradigme.dat")
0253 
0254 # Vis orda me *har* brukt i omsettingane men
0255 # som no vert ekskluderte …
0256 cat("Ord brukte i omsetjingane som no vert forbodne:")
0257 d_frek %>% 
0258         filter(OPPSLAG %in% ord_ekskluder) %>% 
0259         print(n=Inf)