1 Dataset

The first half of the analysis was performed using python - from obtaining the dataset to converting it to the appropriate format. I obtained a list of songs with their chords by scraping a website called <www.ukutabs.com> using library BeautifulSoup. I looped through all pages of songs and got a database as below.

song.base %>% colnames
## [1] "X"               "index"           "title"           "artist"         
## [5] "album"           "genres"          "chordsInSong"    "allChordsInSong"
## [9] "sectionNames"

Since some of the chords have the same notes on a ukulele because of its fewer strings, I had to remove these duplications, like Dm7 and F6.

hide chord pairs

show chord pairs

These are the pairs that turned out to be duplicated based on the notes in chords: > Dm7 = F6
D6 = Bm7
Dsus2 = Asus4
Dm9 = Fmaj7
Gbm7 = A6
F9 = Cm6
Bsus2 = Gbsus4
Bsus4 = Esus2
Fsus4 = Bbsus2
Bb = Bb7
Fm6 = Bbadd9
Bm6 = E9
Dbm6 = Bbdim
Bbm7 = Bbm
Dbsus4 = Gbsus2
Bbsus4 = Ebsus2 = Cm7 = Eb6
Gb6 = Ebm7
C6 = Am7
Csus4 = Fsus2
G6 = Em7
Gsus2 = Dsus4
Gsus4 = Csus2
Cm = Abmaj7

Using the read.transactions() function I am converting the imported csv into an appropriate format for further analysis.

song.basket<-read.transactions("usl/chords/chords/song_basket_df.csv", format='basket', sep=",", skip=1)

On the plot below are 20 most popular chords ordered by frequency. The first conclusion that comes to mind is that the first chords are from DMajor and CMajor keys. It is also visible right away that the most popular chords are the easiest ones. For music played analogous this is still a criterion - the music keys used are simple. That is because it is hard to play in ex. A-flat minor key. This tendency however changed with electronic music where halftones are used for a bizzare, interesting effect.

ifreq <- itemFrequency(song.basket, type="absolute")
ifreq <- base::sort(ifreq, decreasing=T)[0:20]
barplot(ifreq, col='#67d4c0')

2 Cross tables

Below are crosstables for 15 most frequent chords.

count

ctab<-crossTable(song.basket, measure="count", sort=TRUE)[1:15,1:15]
kable(ctab)
G C D A F E Am Em B Bb Bm Ab Gb Eb Dm
G 2686 1797 1640 1022 1108 440 1212 1168 240 304 752 169 188 167 462
C 1797 2362 1035 501 1385 346 1285 939 217 536 289 172 107 188 682
D 1640 1035 2218 1320 395 683 541 953 275 198 865 102 199 141 172
A 1022 501 1320 2049 333 1097 286 454 652 222 749 170 294 114 208
F 1108 1385 395 333 1824 238 987 374 108 740 118 200 124 368 736
E 440 346 683 1097 238 1514 256 179 805 107 296 138 401 87 115
Am 1212 1285 541 286 987 256 1489 597 133 211 177 89 66 84 444
Em 1168 939 953 454 374 179 597 1304 141 92 405 59 85 69 201
B 240 217 275 652 108 805 133 141 1153 106 103 167 520 92 52
Bb 304 536 198 222 740 107 211 92 106 1123 66 396 108 578 418
Bm 752 289 865 749 118 296 177 405 103 66 975 46 128 38 64
Ab 169 172 102 170 200 138 89 59 167 396 46 939 327 534 61
Gb 188 107 199 294 124 401 66 85 520 108 128 327 923 120 39
Eb 167 188 141 114 368 87 84 69 92 578 38 534 120 879 105
Dm 462 682 172 208 736 115 444 201 52 418 64 61 39 105 858

support

stab<-crossTable(song.basket, measure="support", sort=TRUE)[1:15,1:15]
kable(round(stab, 2))
G C D A F E Am Em B Bb Bm Ab Gb Eb Dm
G 0.50 0.33 0.30 0.19 0.20 0.08 0.22 0.22 0.04 0.06 0.14 0.03 0.03 0.03 0.09
C 0.33 0.44 0.19 0.09 0.26 0.06 0.24 0.17 0.04 0.10 0.05 0.03 0.02 0.03 0.13
D 0.30 0.19 0.41 0.24 0.07 0.13 0.10 0.18 0.05 0.04 0.16 0.02 0.04 0.03 0.03
A 0.19 0.09 0.24 0.38 0.06 0.20 0.05 0.08 0.12 0.04 0.14 0.03 0.05 0.02 0.04
F 0.20 0.26 0.07 0.06 0.34 0.04 0.18 0.07 0.02 0.14 0.02 0.04 0.02 0.07 0.14
E 0.08 0.06 0.13 0.20 0.04 0.28 0.05 0.03 0.15 0.02 0.05 0.03 0.07 0.02 0.02
Am 0.22 0.24 0.10 0.05 0.18 0.05 0.27 0.11 0.02 0.04 0.03 0.02 0.01 0.02 0.08
Em 0.22 0.17 0.18 0.08 0.07 0.03 0.11 0.24 0.03 0.02 0.07 0.01 0.02 0.01 0.04
B 0.04 0.04 0.05 0.12 0.02 0.15 0.02 0.03 0.21 0.02 0.02 0.03 0.10 0.02 0.01
Bb 0.06 0.10 0.04 0.04 0.14 0.02 0.04 0.02 0.02 0.21 0.01 0.07 0.02 0.11 0.08
Bm 0.14 0.05 0.16 0.14 0.02 0.05 0.03 0.07 0.02 0.01 0.18 0.01 0.02 0.01 0.01
Ab 0.03 0.03 0.02 0.03 0.04 0.03 0.02 0.01 0.03 0.07 0.01 0.17 0.06 0.10 0.01
Gb 0.03 0.02 0.04 0.05 0.02 0.07 0.01 0.02 0.10 0.02 0.02 0.06 0.17 0.02 0.01
Eb 0.03 0.03 0.03 0.02 0.07 0.02 0.02 0.01 0.02 0.11 0.01 0.10 0.02 0.16 0.02
Dm 0.09 0.13 0.03 0.04 0.14 0.02 0.08 0.04 0.01 0.08 0.01 0.01 0.01 0.02 0.16

lift

ltab<-crossTable(song.basket, measure="lift", sort=TRUE)[1:15,1:15]
kable(round(ltab,2))
G C D A F E Am Em B Bb Bm Ab Gb Eb Dm
G NA 1.54 1.49 1.01 1.23 0.59 1.64 1.81 0.42 0.55 1.56 0.36 0.41 0.38 1.09
C 1.54 NA 1.07 0.56 1.74 0.52 1.98 1.65 0.43 1.10 0.68 0.42 0.27 0.49 1.82
D 1.49 1.07 NA 1.57 0.53 1.10 0.89 1.79 0.58 0.43 2.17 0.27 0.53 0.39 0.49
A 1.01 0.56 1.57 NA 0.48 1.92 0.51 0.92 1.50 0.52 2.03 0.48 0.84 0.34 0.64
F 1.23 1.74 0.53 0.48 NA 0.47 1.97 0.85 0.28 1.96 0.36 0.63 0.40 1.24 2.55
E 0.59 0.52 1.10 1.92 0.47 NA 0.62 0.49 2.50 0.34 1.09 0.53 1.56 0.35 0.48
Am 1.64 1.98 0.89 0.51 1.97 0.62 NA 1.67 0.42 0.68 0.66 0.35 0.26 0.35 1.88
Em 1.81 1.65 1.79 0.92 0.85 0.49 1.67 NA 0.51 0.34 1.73 0.26 0.38 0.33 0.97
B 0.42 0.43 0.58 1.50 0.28 2.50 0.42 0.51 NA 0.44 0.50 0.84 2.65 0.49 0.28
Bb 0.55 1.10 0.43 0.52 1.96 0.34 0.68 0.34 0.44 NA 0.33 2.04 0.56 3.17 2.35
Bm 1.56 0.68 2.17 2.03 0.36 1.09 0.66 1.73 0.50 0.33 NA 0.27 0.77 0.24 0.41
Ab 0.36 0.42 0.27 0.48 0.63 0.53 0.35 0.26 0.84 2.04 0.27 NA 2.04 3.51 0.41
Gb 0.41 0.27 0.53 0.84 0.40 1.56 0.26 0.38 2.65 0.56 0.77 2.04 NA 0.80 0.27
Eb 0.38 0.49 0.39 0.34 1.24 0.35 0.35 0.33 0.49 3.17 0.24 3.51 0.80 NA 0.75
Dm 1.09 1.82 0.49 0.64 2.55 0.48 1.88 0.97 0.28 2.35 0.41 0.41 0.27 0.75 NA

probability

ptab<-crossTable(song.basket, measure="probability", sort=TRUE)[1:15,1:15]
kable(round(ptab, 2))
G C D A F E Am Em B Bb Bm Ab Gb Eb Dm
G 0.50 0.33 0.30 0.19 0.20 0.08 0.22 0.22 0.04 0.06 0.14 0.03 0.03 0.03 0.09
C 0.33 0.44 0.19 0.09 0.26 0.06 0.24 0.17 0.04 0.10 0.05 0.03 0.02 0.03 0.13
D 0.30 0.19 0.41 0.24 0.07 0.13 0.10 0.18 0.05 0.04 0.16 0.02 0.04 0.03 0.03
A 0.19 0.09 0.24 0.38 0.06 0.20 0.05 0.08 0.12 0.04 0.14 0.03 0.05 0.02 0.04
F 0.20 0.26 0.07 0.06 0.34 0.04 0.18 0.07 0.02 0.14 0.02 0.04 0.02 0.07 0.14
E 0.08 0.06 0.13 0.20 0.04 0.28 0.05 0.03 0.15 0.02 0.05 0.03 0.07 0.02 0.02
Am 0.22 0.24 0.10 0.05 0.18 0.05 0.27 0.11 0.02 0.04 0.03 0.02 0.01 0.02 0.08
Em 0.22 0.17 0.18 0.08 0.07 0.03 0.11 0.24 0.03 0.02 0.07 0.01 0.02 0.01 0.04
B 0.04 0.04 0.05 0.12 0.02 0.15 0.02 0.03 0.21 0.02 0.02 0.03 0.10 0.02 0.01
Bb 0.06 0.10 0.04 0.04 0.14 0.02 0.04 0.02 0.02 0.21 0.01 0.07 0.02 0.11 0.08
Bm 0.14 0.05 0.16 0.14 0.02 0.05 0.03 0.07 0.02 0.01 0.18 0.01 0.02 0.01 0.01
Ab 0.03 0.03 0.02 0.03 0.04 0.03 0.02 0.01 0.03 0.07 0.01 0.17 0.06 0.10 0.01
Gb 0.03 0.02 0.04 0.05 0.02 0.07 0.01 0.02 0.10 0.02 0.02 0.06 0.17 0.02 0.01
Eb 0.03 0.03 0.03 0.02 0.07 0.02 0.02 0.01 0.02 0.11 0.01 0.10 0.02 0.16 0.02
Dm 0.09 0.13 0.03 0.04 0.14 0.02 0.08 0.04 0.01 0.08 0.01 0.01 0.01 0.02 0.16
# {-}

3 Most frequent items

freq.items <- eclat(song.basket, parameter=list(supp=0.2, maxlen=15))
freq.rules<-ruleInduction(freq.items, song.basket, confidence=0.5)

The most popular pairs are the ones within one key. For example for the first pair Em is a closely related key of G, the same with Am and C. For C,G with Am, the notes of all belong to the same key - C or Am. In music theory, Am to C is the submediant. F, G are its subdominant and dominant. These are the easiest and most commonly used harmonies.

For Em as lhs and G as rhs, 20% of songs have both of them together. What is more, is that in the presence of Em there is a 89.5% chance that the song contains G too.

inspect(head(freq.rules))
##     lhs       rhs  support   confidence lift     itemset
## [1] {Em}   => {G}  0.2154982 0.8957055  1.807418 1      
## [2] {C,G}  => {Am} 0.2033210 0.6132443  2.232226 2      
## [3] {Am,G} => {C}  0.2033210 0.9092409  2.086404 2      
## [4] {Am,C} => {G}  0.2033210 0.8575875  1.730501 2      
## [5] {Am}   => {G}  0.2236162 0.8139691  1.642484 3      
## [6] {C}    => {Am} 0.2370849 0.5440305  1.980286 4

4 Association rules - combinations

4.1 Association between a minimum of 4 chords

By reducing the number of parameters and setting the minimal number of components to 4 the results get much more interesting.

freq.items<-eclat(song.basket, parameter=list(supp=0.1, minlen=4)) 
freq.rules<-ruleInduction(freq.items, song.basket, confidence=0.5)
inspect(freq.items)
##     items      support   count
## [1] {C,D,Em,G} 0.1162362 630  
## [2] {Am,C,F,G} 0.1398524 758
inspect(freq.rules)
##     lhs         rhs  support   confidence lift     itemset
## [1] {D,Em,G} => {C}  0.1162362 0.7134768  1.637191 1      
## [2] {C,Em,G} => {D}  0.1162362 0.7274827  1.777708 1      
## [3] {C,D,G}  => {Em} 0.1162362 0.6680806  2.776838 1      
## [4] {C,D,Em} => {G}  0.1162362 0.9431138  1.903081 1      
## [5] {C,F,G}  => {Am} 0.1398524 0.7595190  2.764670 2      
## [6] {Am,F,G} => {C}  0.1398524 0.9369592  2.150008 2      
## [7] {Am,C,G} => {F}  0.1398524 0.6878403  2.043911 2      
## [8] {Am,C,F} => {G}  0.1398524 0.8394241  1.693849 2

I am printing rules that have decent support and confidence and see the ones with the highest confidence and support (through sorting below).

rules.chords<-apriori(song.basket, parameter=list(supp=0.15, conf=0.5, minlen=3)) 
rules.by.conf<-sort(rules.chords, by="confidence", decreasing=TRUE) 
head(inspect(rules.by.conf))
##      lhs       rhs  support   confidence lift     count
## [1]  {D,Em} => {G}  0.1629151 0.9265477  1.869653  883 
## [2]  {C,Em} => {G}  0.1597786 0.9222577  1.860997  866 
## [3]  {Am,F} => {C}  0.1666052 0.9148936  2.099375  903 
## [4]  {C,D}  => {G}  0.1739852 0.9111111  1.838504  943 
## [5]  {Am,G} => {C}  0.2033210 0.9092409  2.086404 1102 
## [6]  {F,G}  => {C}  0.1841328 0.9007220  2.066856  998 
## [7]  {Am,C} => {G}  0.2033210 0.8575875  1.730501 1102 
## [8]  {A,G}  => {D}  0.1601476 0.8493151  2.075423  868 
## [9]  {Em,G} => {D}  0.1629151 0.7559932  1.847377  883 
## [10] {Em,G} => {C}  0.1597786 0.7414384  1.701353  866 
## [11] {C,F}  => {G}  0.1841328 0.7205776  1.454032  998 
## [12] {Am,C} => {F}  0.1666052 0.7027237  2.088137  903 
## [13] {A,D}  => {G}  0.1601476 0.6575758  1.326903  868 
## [14] {C,F}  => {Am} 0.1666052 0.6519856  2.373245  903 
## [15] {C,G}  => {Am} 0.2033210 0.6132443  2.232226 1102 
## [16] {D,G}  => {C}  0.1739852 0.5750000  1.319433  943 
## [17] {C,G}  => {F}  0.1841328 0.5553701  1.650277  998 
## [18] {D,G}  => {Em} 0.1629151 0.5384146  2.237889  883 
## [19] {D,G}  => {A}  0.1601476 0.5292683  1.400017  868 
## [20] {C,G}  => {D}  0.1739852 0.5247635  1.282335  943
##        lhs    rhs   support confidence     lift count
## [1] {D,Em} => {G} 0.1629151  0.9265477 1.869653   883
## [2] {C,Em} => {G} 0.1597786  0.9222577 1.860997   866
## [3] {Am,F} => {C} 0.1666052  0.9148936 2.099375   903
## [4]  {C,D} => {G} 0.1739852  0.9111111 1.838504   943
## [5] {Am,G} => {C} 0.2033210  0.9092409 2.086404  1102
## [6]  {F,G} => {C} 0.1841328  0.9007220 2.066856   998
rules.by.supp<-sort(rules.chords, by="support", decreasing=TRUE) 
inspect(head(rules.by.supp))
##     lhs       rhs  support   confidence lift     count
## [1] {Am,C} => {G}  0.2033210 0.8575875  1.730501 1102 
## [2] {Am,G} => {C}  0.2033210 0.9092409  2.086404 1102 
## [3] {C,G}  => {Am} 0.2033210 0.6132443  2.232226 1102 
## [4] {C,F}  => {G}  0.1841328 0.7205776  1.454032  998 
## [5] {F,G}  => {C}  0.1841328 0.9007220  2.066856  998 
## [6] {C,G}  => {F}  0.1841328 0.5553701  1.650277  998

And then plotting the results.

plot(rules.chords, method="graph")

4.2 Association between chords with the highest confidence

rules.chords<-apriori(song.basket, parameter=list(supp=0.1, conf=0.9)) 
rules.by.conf<-sort(rules.chords, by="confidence", decreasing=TRUE) 
inspect(head(rules.by.conf))
##     lhs         rhs support   confidence lift     count
## [1] {C,D,Em} => {G} 0.1162362 0.9431138  1.903081 630  
## [2] {Am,F,G} => {C} 0.1398524 0.9369592  2.150008 758  
## [3] {D,Em}   => {G} 0.1629151 0.9265477  1.869653 883  
## [4] {A,Bm}   => {D} 0.1274908 0.9225634  2.254416 691  
## [5] {C,Em}   => {G} 0.1597786 0.9222577  1.860997 866  
## [6] {Bm,G}   => {D} 0.1271218 0.9162234  2.238923 689
rules.by.supp<-sort(rules.chords, by="support", decreasing=TRUE) 
inspect(head(rules.by.supp))
##     lhs       rhs support   confidence lift     count
## [1] {Am,G} => {C} 0.2033210 0.9092409  2.086404 1102 
## [2] {F,G}  => {C} 0.1841328 0.9007220  2.066856  998 
## [3] {C,D}  => {G} 0.1739852 0.9111111  1.838504  943 
## [4] {Am,F} => {C} 0.1666052 0.9148936  2.099375  903 
## [5] {D,Em} => {G} 0.1629151 0.9265477  1.869653  883 
## [6] {C,Em} => {G} 0.1597786 0.9222577  1.860997  866
plot(rules.chords, method="graph")

4.3 Associations with the highest support

rules.chords<-apriori(song.basket, parameter=list(supp=0.25, conf=0.1)) 
## Apriori
## 
## Parameter specification:
##  confidence minval smax arem  aval originalSupport maxtime support minlen
##         0.1    0.1    1 none FALSE            TRUE       5    0.25      1
##  maxlen target   ext
##      10  rules FALSE
## 
## Algorithmic control:
##  filter tree heap memopt load sort verbose
##     0.1 TRUE TRUE  FALSE TRUE    2    TRUE
## 
## Absolute minimum support count: 1355 
## 
## set item appearances ...[0 item(s)] done [0.00s].
## set transactions ...[131 item(s), 5420 transaction(s)] done [0.02s].
## sorting and recoding items ... [7 item(s)] done [0.00s].
## creating transaction tree ... done [0.00s].
## checking subsets of size 1 2 done [0.00s].
## writing ... [13 rule(s)] done [0.00s].
## creating S4 object  ... done [0.00s].
rules.by.conf<-sort(rules.chords, by="confidence", decreasing=TRUE) 
inspect(head(rules.by.conf))
##     lhs    rhs support   confidence lift     count
## [1] {C} => {G} 0.3315498 0.7607959  1.535188 1797 
## [2] {F} => {C} 0.2555351 0.7593202  1.742386 1385 
## [3] {D} => {G} 0.3025830 0.7394049  1.492023 1640 
## [4] {G} => {C} 0.3315498 0.6690246  1.535188 1797 
## [5] {G} => {D} 0.3025830 0.6105733  1.492023 1640 
## [6] {C} => {F} 0.2555351 0.5863675  1.742386 1385
rules.by.supp<-sort(rules.chords, by="support", decreasing=TRUE) 
inspect(head(rules.by.supp))
##     lhs    rhs support   confidence lift     count
## [1] {}  => {G} 0.4955720 0.4955720  1.000000 2686 
## [2] {}  => {C} 0.4357934 0.4357934  1.000000 2362 
## [3] {}  => {D} 0.4092251 0.4092251  1.000000 2218 
## [4] {}  => {A} 0.3780443 0.3780443  1.000000 2049 
## [5] {}  => {F} 0.3365314 0.3365314  1.000000 1824 
## [6] {C} => {G} 0.3315498 0.7607959  1.535188 1797
plot(rules.chords, method="graph")

4.4 Association with reasonable support, confidence and minlen=2

rules.chords<-apriori(song.basket, parameter=list(supp=0.1, conf=0.4, minlen=2)) 
rules.by.conf<-sort(rules.chords, by="confidence", decreasing=TRUE) 
inspect(head(rules.by.conf))
##     lhs         rhs support   confidence lift     count
## [1] {C,D,Em} => {G} 0.1162362 0.9431138  1.903081 630  
## [2] {Am,F,G} => {C} 0.1398524 0.9369592  2.150008 758  
## [3] {D,Em}   => {G} 0.1629151 0.9265477  1.869653 883  
## [4] {A,Bm}   => {D} 0.1274908 0.9225634  2.254416 691  
## [5] {C,Em}   => {G} 0.1597786 0.9222577  1.860997 866  
## [6] {Bm,G}   => {D} 0.1271218 0.9162234  2.238923 689
rules.by.supp<-sort(rules.chords, by="support", decreasing=TRUE) 
inspect(head(rules.by.supp))
##     lhs    rhs support   confidence lift     count
## [1] {C} => {G} 0.3315498 0.7607959  1.535188 1797 
## [2] {G} => {C} 0.3315498 0.6690246  1.535188 1797 
## [3] {D} => {G} 0.3025830 0.7394049  1.492023 1640 
## [4] {G} => {D} 0.3025830 0.6105733  1.492023 1640 
## [5] {F} => {C} 0.2555351 0.7593202  1.742386 1385 
## [6] {C} => {F} 0.2555351 0.5863675  1.742386 1385

Not much can really be visible:

plot(rules.chords, method="graph")

But here it looks better.

plot(rules.chords, method="grouped", lhs_items=6, rhs_max = 13)

5 Finding associations for favorite chords

Why do that, I actually used this recently composing a song when I wanted to add my favorite chords - I looked for associations for this chord.

rules.A7sus4<-apriori(data=song.basket, parameter=list(supp=0.01,conf = 0.08, minlen=2), appearance = list(default="rhs",lhs="A7sus4")) 
inspect(rules.A7sus4)
rules.A5<-apriori(data=song.basket, parameter=list(minlen=2,supp=0.00001,conf = 0.008), appearance = list(default="rhs",lhs="A5")) 
head(inspect(rules.A5))
##      lhs     rhs     support      confidence lift       count
## [1]  {A5} => {Bm6}   0.0001845018 0.5        903.333333 1    
## [2]  {A5} => {A9}    0.0001845018 0.5        677.500000 1    
## [3]  {A5} => {Amaj7} 0.0001845018 0.5         66.097561 1    
## [4]  {A5} => {Abm7}  0.0001845018 0.5         69.487179 1    
## [5]  {A5} => {Ab7}   0.0001845018 0.5         47.543860 1    
## [6]  {A5} => {Gbm7}  0.0001845018 0.5         35.657895 1    
## [7]  {A5} => {B7}    0.0001845018 0.5         13.756345 1    
## [8]  {A5} => {Dbm}   0.0001845018 0.5          4.201550 1    
## [9]  {A5} => {Ab}    0.0001845018 0.5          2.886049 1    
## [10] {A5} => {B}     0.0001845018 0.5          2.350390 1    
## [11] {A5} => {E}     0.0003690037 1.0          3.579921 2    
## [12] {A5} => {A}     0.0003690037 1.0          2.645193 2    
## [13] {A5} => {D}     0.0001845018 0.5          1.221821 1
##      lhs        rhs      support confidence      lift count
## [1] {A5} =>   {Bm6} 0.0001845018        0.5 903.33333     1
## [2] {A5} =>    {A9} 0.0001845018        0.5 677.50000     1
## [3] {A5} => {Amaj7} 0.0001845018        0.5  66.09756     1
## [4] {A5} =>  {Abm7} 0.0001845018        0.5  69.48718     1
## [5] {A5} =>   {Ab7} 0.0001845018        0.5  47.54386     1
## [6] {A5} =>  {Gbm7} 0.0001845018        0.5  35.65789     1
rules.A9<-apriori(data=song.basket, parameter=list(minlen=2,supp=0.0002,conf = 0.008), appearance = list(default="rhs",lhs="A9")) 
inspect(rules.A9)
##     lhs     rhs    support      confidence lift      count
## [1] {A9} => {Abm7} 0.0003690037 0.5        69.487179 2    
## [2] {A9} => {Gm7}  0.0003690037 0.5        34.303797 2    
## [3] {A9} => {Dm7}  0.0003690037 0.5        25.809524 2    
## [4] {A9} => {B7}   0.0003690037 0.5        13.756345 2    
## [5] {A9} => {A7}   0.0003690037 0.5        13.550000 2    
## [6] {A9} => {E7}   0.0003690037 0.5        12.374429 2    
## [7] {A9} => {G}    0.0003690037 0.5         1.008935 2

6 Conclusions

So what can be told about the results. For sure it can be seen that the most popular chords are the easy ones and when it comes to pairs the chords that go together are most likely to be from the same key or related keys. What is more the results that were output from the analysis above can be used in songwriting.