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.
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')
Below are crosstables for 15 most frequent chords.
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 |
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 |
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 |
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 |
# {-} |
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
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")
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")
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")
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)
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
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.