resources/images/dhlab-logo-nb.png

import dhlab as dh
from dhlab.api.dhlab_api import totals
import dhlab.nbtext as nb

1.5. Kollokasjoner#

Kollokasjoner er assosiasjoner.

I denne notebooken viser vi eksempler på undersøkelser man kan gjøre for å finne ut hvilke ord et ord opptrer sammen med innenfor et korpus.

1.5.1. Konstruer et korpus med Dewey#

Se eksempelfil om Korpusbygging for andre måter å definere korpus.

For å finne relevant dewey-klassifikasjon kan Webdewey være til god hjelp.

# korpus med inntil 200 bøker fra dewey 641.2 (drikkevarer) utgitt mellom 1960 og 2020

korpus = dh.Corpus(ddk="641.2%", limit=200)

For å se metadata fra korpuset som dataramme brukes metoden corpus. Man kan bruke head() for å begrense antall rader som vises.

korpus.corpus.head(2)
dhlabid urn title authors oaiid sesamid isbn10 city timestamp year publisher langs subjects ddc genres literaryform doctype ocr_creator ocr_timestamp
0 100089441 URN:NBN:no-nb_digibok_2012071338024 Alt om øl Hillesland , Jan / Åstrøm , Isidor oai:nb.bibsys.no:990317365994702202 1781bc777ce7547b91bee5fa6cc51838 8202232341 [Oslo] 20030101 2003 Cappelen nob Beer / Øl / Kulturkunnskap / Historisk framsti... 641.23 / 641.23 Faglitteratur digibok nb 20060101
1 100420731 URN:NBN:no-nb_digibok_2020100107619 Gylne dager og dype viner : en mat- og vinreis... Hagerup , Klaus / Oftebro , Nils Ole / Karlsen... oai:nb.bibsys.no:991321024044702202 232c473ff14a58d5cf76a99187cf2c14 [Oslo] 20130101 2013 Cappelen Damm nob kokebøker / italia / vin 641.220945 / 641.22 Faglitteratur digibok nb 20060101

1.5.2. Lager kollokasjoner fra korpuset#

Et skrittvis eksempel.

  1. Bygg kollokasjonen

  2. Finn en referanse

  3. Sammenlign kollokasjon med referanse

1.5.2.1. Bygg kollokasjon#

Kommandoen er dh.Collocation. Legg gjerne inn en sjekk med konkordans.

collword = 'rødvin'
# Vi utfører en konkordans for å sjekke at korpuset virker.
# dh.Concordance(corpus=korpus, query="sei").show()
korpus.conc("sei").show()
  link concordance
2 URN:NBN:no-nb_digibok_2018031548126 Det er ikke uten grunn at melstekt sei går under betegnelsen seibiff . For seiv om seien er en hvit...
3 URN:NBN:no-nb_digibok_2020112407621 ... Så skulle ølet " skakast ned " , det vil sei fyllast over på tunna . Då smaka dei gjerne på ølet...
7 URN:NBN:no-nb_digibok_2020120907530 Bedales of Borough Market 5 Bedale St , London SEI 9 AL
1 URN:NBN:no-nb_digibok_2020112407621 Sjå Løksli de ligg no so fint fram mæ li , no sei dei at Knut vil te Mæland å...
4 URN:NBN:no-nb_digibok_2018031548126 ... den enkelte råvare og tilberedningsmetoden det handler om . Sei har en litt tyngre smak , ser litt gråere ut...
0 URN:NBN:no-nb_digibok_2020112407621 ... Ved Bull Run gik de reint gæli . " " Men sei me no du Jørn , håfør ha med denna krigen...
5 URN:NBN:no-nb_digibok_2018031548126 vin til melstekt sei
6 URN:NBN:no-nb_digibok_2018042548149 ... men O HVIT FISK , nesten alt går . Sei , hyse , kolje , kveite , hva som helst...

Så kan vi hente ut selve kollokasjonen, dvs. ord som står innenfor en viss avstand fra målordet.

# Vi legger inn variablen collword som søkeord, med 5 ord før og etter. 
#  Antall ord før og etter kan endres etter konteksten man vil undersøke.
# Collword er lagt som variabel i cella over, slik at det er lett å gjenbruke notebooken for ulike søkeord

coll = korpus.coll(words=collword, after=5, before=5, samplesize=1000)
# For å vise topp `n` treff bruke .show().head(n)
coll.show().head(5)
counts
. 371
, 364
og 247
en 224
med 158

Kollokasjonen ligger i en såkalt dataframe som kan undersøkes med .head() som ovenfor. Man får adgang til datarammen gjennom coll metoden.

coll.coll.sort_values(by="counts", ascending=False).head(10)
counts
. 371
, 364
og 247
en 224
med 158
er 123
som 110
i 100
til 98
av 83

1.5.2.2. Finn referanse#

Det er flere måter å sammenligne på. En er å bruke bokhylla selv om som referanse. For å hente ut ord fra bokhylla brukes kommandoen totals(<antall ord>). Korpuset selv kan også benyttes, for eksempel med kommandoen aggregate_urns(<korpusdefinisjon>).

1.5.2.2.1. Bokhylla aggregert#

totals inneholder råfrekvenser fra Nasjonalbibliotekets katalog.

tot = totals(50000)
tot.head()
freq
. 7655423257
, 5052171514
i 2531262027
og 2520268056
- 1314451583

1.5.2.2.2. Aggregert korpus#

# dh.Counts teller tokens i hver tekst i korpus
dokumenter_aggregert = korpus.count(words=None)
# Summerer slik at vi får totalt tokens for korpus
korpus_agg = dokumenter_aggregert.counts.sum(axis=1)

Gjør den om til dataramme, sorterer og ser på resultatet

  1. Dataramme med kommando frame()

  2. Sortering med frame_sort() definert øverst i den her notebooken.

korpus_agg = nb.frame_sort(nb.frame(korpus_agg))
korpus_agg.head(10)
0
, 101992.0
. 100198.0
og 57767.0
i 46178.0
er 36294.0
som 28769.0
en 26301.0
av 26272.0
det 23581.0
med 23076.0

1.5.2.3. Sammenlign#

Vi har nå tre frekvenslister som kan sammenlignes med hverandre. For å lette sammenlign normaliseres dem. Kommandoen for normalisering er normalize_corpus_dataframe(<frekvensliste>)

coll.coll.sort_values(by="counts", ascending=False)
counts
. 371
, 364
og 247
en 224
med 158
... ...
ørret 1
øvrig 1
årene 1
året 1
årgang 1

1727 rows × 1 columns

coll_df = coll.coll.copy()
coll_df.sort_values(by="counts", ascending=False)
counts
. 371
, 364
og 247
en 224
med 158
... ...
ørret 1
øvrig 1
årene 1
året 1
årgang 1

1727 rows × 1 columns

nb.normalize_corpus_dataframe(korpus_agg)
nb.normalize_corpus_dataframe(tot)
nb.normalize_corpus_dataframe(coll_df)
True

Inspiser dataene etter normalisering

1.5.2.3.1. Aggregert korpus#

Fyll inn verdier for .head() for å se mer.

korpus_agg.head()
0
, 0.048208
. 0.047361
og 0.027305
i 0.021827
er 0.017155

1.5.2.3.2. Bokhylla total#

tot.head()
freq
. 0.070908
, 0.046796
i 0.023446
og 0.023344
- 0.012175

1.5.2.3.3. Kollokasjonen#

coll.coll.head()
counts
! 8
" 3
$ 1
% 5
' 2

Kollokasjonen coll har gjennomgående høyere verdier, noe som sannsynligvis skyldes at det er færre ord.

1.5.2.3.4. Utfør sammenligning#

For sammenligning måles forskjellen på coll med referansen. Forskjellen måles ved å dividere hvert ords frekvens ikollokasjonen på frekvensen ordet har i referansen.

\[\textrm{assosiasjons-styrke}(w) = \frac{\textrm{coll}(w)}{\textrm{referanse}(w)}\]

Divisjonen pr.ord gjøres av Python - resultat sorteres og legges i variabelen coll_assoc

coll_assoc = (coll_df.counts**1.0/tot.freq).sort_values(ascending=False).to_frame()
coll_assoc.head(20)
0
hvitvin 7026.044871
saftig 1417.672096
rødvin 647.515803
kirsebær 629.299777
bobler 575.216457
timian 567.767653
druer 512.780650
fyldig 447.497598
østerriksk 444.506454
Øvrig 402.551003
drikkes 396.165570
panna 371.495656
syre 305.530248
Toscana 288.703884
Tilsett 287.683179
solbær 286.884032
bløt 274.143545
italiensk 257.595151
portugisisk 256.972971
australsk 241.191116

1.5.2.3.5. 2.3.5. Sammenlign med korpus#

Her kan det være nyttig å bruke en eksponent for å dempe effekten av lavfrekvente ord.

korpus_agg
0
, 4.820849e-02
. 4.736052e-02
og 2.730469e-02
i 2.182692e-02
er 1.715506e-02
... ...
småvokste 4.726693e-07
smørblomster 4.726693e-07
smørbrødmarkedet 4.726693e-07
smørbrødosten 4.726693e-07
smørbrødsteder 4.726693e-07

127719 rows × 1 columns

coll_assoc_korp = (coll_df.counts**1.2/korpus_agg.iloc[:, 0]).sort_values().to_frame()
coll_assoc_korp.head(20)
0
100 0.017447
% 0.021806
han 0.024867
' 0.025543
alle 0.029087
30 0.033393
40 0.034091
g 0.035513
store 0.036165
hvor 0.037447
OG 0.039604
får 0.039936
0.040303
deg 0.042399
0.043664
° 0.043933
kunne 0.044690
noen 0.046052
C 0.046701
år 0.049013

1.5.3. Visualiser med en ordsky#

Visualiseringen trives best med tall mellom 0 og 1, så assosiasjonene divideres på summen av dem for å få til det. Ordskyene lages med kommonandoen cloud(<data>). Pass på å ikke ta med alt for mange; det kan gi feilsituasjoner.

# Her viser vi de 50 viktigste ordene som er assosiert med rødvin i korpuset vårt, målt mot alle bøker i nb.no 

nb.cloud(coll_assoc.head(50)/coll_assoc.sum())
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[27], line 3
      1 # Her viser vi de 50 viktigste ordene som er assosiert med rødvin i korpuset vårt, målt mot alle bøker i nb.no 
----> 3 nb.cloud(coll_assoc.head(50)/coll_assoc.sum())

File ~/prosjekter/DHLAB/dhlab/legacy/nbtext.py:1529, in cloud(df, column, top, width, height, background, file, stretch, font_path)
   1527     column = df.columns[0]
   1528 data = json.loads(df[column].to_json())
-> 1529 a_cloud = make_cloud(
   1530     data,
   1531     top=top,
   1532     background=background,
   1533     font_path=font_path,
   1534     stretch=lambda x: 2 ** (stretch * x),
   1535     width=width,
   1536     height=height,
   1537 )
   1538 draw_cloud(a_cloud, fil=file)

File ~/prosjekter/DHLAB/dhlab/legacy/nbtext.py:1493, in make_cloud(json_text, top, background, stretch, width, height, font_path)
   1491 pairs0 = Counter(json_text).most_common(top)
   1492 pairs = {x[0]: stretch(x[1]) for x in pairs0}
-> 1493 wc = WordCloud(
   1494     font_path=font_path,
   1495     background_color=background,
   1496     width=width,
   1497     # color_func=my_colorfunc,
   1498     ranks_only=True,
   1499     height=height,
   1500 ).generate_from_frequencies(pairs)
   1501 return wc

NameError: name 'WordCloud' is not defined
# Her viser vi de 50 viktigste ordene som er assosiert med rødvin, målt mot hele "Drikkevare"-korpuset

nb.cloud(coll_assoc_korp.head(50)/coll_assoc_korp.sum())
../_images/a30709237f4d292bdcd993096a535f9b0521043ebe3d85d80efa119deb7318bb.png

1.5.4. Gjenbruk med andre ord og korpus#

  1. Bytt ut parametrene i cellen der korpus blir definert.

  2. Bytt ut ordet som er angitt som collword.

  3. Gå til Cell i menyen og velg Run All.

Det er også mulig å først velge File og Make a Copy, slik at man oppretter en ny notebook før man starter.

Tilbake til DHLAB ved Nasjonalbiblioteket