-
Notifications
You must be signed in to change notification settings - Fork 1
/
JT_app_v1.R
275 lines (174 loc) · 9.02 KB
/
JT_app_v1.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
library(shiny)
library(dplyr)
library(readr)
# load list of last.fm artists: drop columns containing URL's since they aren't needed
lfm_art <- read_delim("https://raw.githubusercontent.com/jtopor/CUNY-MSDA-643/master/FP/artists.dat", delim = "\t") %>% select(id, name)
# cleanup foreign characters in artist names: most will be converted to '?'
lfm_art$name <- iconv(lfm_art$name, from = "UTF-8", to = "ASCII//TRANSLIT")
# load last.fm tags.dat file to get access to genre names
lfm_tags <- read_delim("https://raw.githubusercontent.com/jtopor/CUNY-MSDA-643/master/FP/tags.dat", delim = "\t")
# load required matrices
# ------------------------
# load artist-genre matrix
ag_mat <- as.matrix(read.csv("https://raw.githubusercontent.com/RobertSellers/R_Shiny_Recommender/master/R-Obj-CSVs/ag_mat.csv", check.names = FALSE,
header=TRUE, sep = ",", stringsAsFactors = FALSE) )
# set rownames to values in V1
row.names(ag_mat) <- as.numeric(ag_mat[,1])
# now truncate matrix to eliminate col 1
ag_mat <- ag_mat[,2:ncol(ag_mat)]
# --------------------------
# ----------------------------
# load artist similarity matrix
art_sim <- as.matrix(read.csv("https://raw.githubusercontent.com/RobertSellers/R_Shiny_Recommender/master/R-Obj-CSVs/art_sim.csv", check.names = FALSE,
header=TRUE, sep = ",", stringsAsFactors = FALSE) )
# set rownames to values in V1
row.names(art_sim) <- as.numeric(art_sim[,1])
# now truncate matrix to eliminate col 1
art_sim <- art_sim[,2:ncol(art_sim)]
# ----------------------------
last_sm <- read.csv("https://raw.githubusercontent.com/RobertSellers/R_Shiny_Recommender/master/R-Obj-CSVs/last_sm.csv",
header=TRUE, sep = ",", stringsAsFactors = FALSE)
tenrecs <- read.csv("https://raw.githubusercontent.com/RobertSellers/R_Shiny_Recommender/master/R-Obj-CSVs/user_tenrecs.csv",
header=TRUE, sep = ",", stringsAsFactors = FALSE)
###### Get the top 815 Artists IDS ---------------
# extract the 815 top artist IDs from art_sim matrix and convert to numeric
artistIDs <- as.numeric(rownames(art_sim) )
# then get associated genre names from lfm_art data frame
a_names <- lfm_art[lfm_art$id %in% artistIDs,]$name
# remove artist names that start with '?' characters since they cause problems
# when trying to later retrieve the associated artist ID
a_names <- a_names[a_names != '????']
a_names <- a_names[a_names != '?????']
a_names <- a_names[a_names != '??????']
#------------------------------------------------
###### Get the list of the top 200 genre names ----
# extract the genre tagIDs from artist-genre matrix and convert to numeric
tagIDs <- as.numeric(colnames(ag_mat))
# then get associated genre names from lfm_tags data frame
g_names <- lfm_tags[lfm_tags$tagID %in% tagIDs,]$tagValue
# --------------------------------------------------
##### Get a list of distinct userID's
userIDs <- unique(last_sm$userID)
u_hdr <- paste("Select a User ID (", min(userIDs), " - ", max(userIDs), " )" )
# ____ui____
ui <- shinyUI(fluidPage(
titlePanel(h1(style = "font-family: Arial Black", "last.fm Artist Recommender")),
sidebarLayout(
sidebarPanel(
selectInput("d_userID", u_hdr,
# choices = userIDs ),
# choices = c(Enter_User_ID='', userIDs )),
choices = c("Enter User ID", userIDs )),
radioButtons("Rec_Choices", label=h4("Select A Recommendation Method:"),
choices = list("Review Artists Listened to Previously" = "last_sm",
"By Similar Artists (Top 5)" = "art_sim",
"By Genre (Top 5)" = "ag_mat",
"10 Artists Recommended by Similar Users" = "tenrecs"),
selected = "tenrecs"),
uiOutput("selectedItem")
), # end sidebarPanel
mainPanel(
h3(textOutput("text")),
br(),
tableOutput("table")
) # end mainPanel
)) # end sidebarLayout
)
############################################################################
############################################################################
# ____server____
server <- shinyServer(function(input, output) {
#############################################
# Function to create dynamic drop down containing appropriate list to choose from
output$selectedItem <- renderUI({
if (input$Rec_Choices == "ag_mat") {
selectInput("d_genre", "Select Genre:",
choices = c("Select a Genre", sort(g_names) ) )
} else if (input$Rec_Choices == "art_sim") {
selectInput("d_artsim", "Select Artist:",
choices = c("Select an Artist", sort(a_names) ) )
} else if (input$Rec_Choices == "last_sm") {
# get list of previously listened artists for userID
user_arts <- last_sm$artistID[last_sm$userID == input$d_userID]
# create list of artist names from artist ID's in list
ul_names <- lfm_art[lfm_art$id %in% user_arts,]$name
# remove any artists that start with ? character
ul_names <- ul_names[ul_names != '????']
ul_names <- ul_names[ul_names != '?????']
ul_names <- ul_names[ul_names != '??????']
selectInput("d_lastsm", "Select an Artist You Have Previously Listened To:",
choices = c("Select an Artist", sort(ul_names) ) )
} # end if
})
##############################################
# Function to generate heading for main panel
output$text<- renderText({
if (input$Rec_Choices == "ag_mat") {
paste("Top 5 Artists in Selected Genre")
} else if (input$Rec_Choices == "art_sim") {
paste("Top 5 Artists Similar to Selected Artist", input$selectedItem)
} else if (input$Rec_Choices == "last_sm") {
paste("Top 5 Artists Similar to Selected Artist", input$selectedItem)
} else if (input$Rec_Choices == "tenrecs") {
paste("10 Artists You May Like")
} # end if
})
##############################################
# function to generate list of recommended artists depending on
# the method selected by the user
output$table <- renderTable({
if (input$Rec_Choices == "ag_mat") {
# Top 5 Artists in Selected Genre
# set number of artists to recommend
n_recommended <- 5
# get tagID of genre
g_tag <- lfm_tags[lfm_tags$tagValue == input$d_genre,]$tagID
# fetch the top N artists:
# the names of the items are the artist IDs
g_arecs <- sort(ag_mat[,as.character(g_tag)], decreasing = TRUE)[1:n_recommended]
# extract the artist IDs and convert to numeric
g_arecs_IDs <- as.numeric(names(g_arecs))
# create list of artist names from artist ID's in list
g_arec_names <- lfm_art[lfm_art$id %in% g_arecs_IDs,]$name
return(g_arec_names)
############################################
} else if (input$Rec_Choices == "art_sim") {
# Top 5 Artists Similar to Selected Artist
n_recommended <- 5
# get name of artist from artist list
a_val <- lfm_art[lfm_art$name == input$d_artsim,]$id
# fetch their recommendations: this returns a named vector sorted by similarity
# the names of the items are the artist IDs
arecs <- sort(art_sim[as.character(a_val),], decreasing = TRUE)[1:n_recommended]
# extract the artist IDs and convert to numeric
arecs_IDs <- as.numeric(names(arecs))
# create list of artist names from artist ID's in list
arec_names <- lfm_art[lfm_art$id %in% arecs_IDs,]$name
return(arec_names)
#############################################
} else if (input$Rec_Choices == "last_sm") {
# Top 5 Artists Similar to Artist Name selected from previous listen list
n_recommended <- 5
# get ID of artist from artist list
a_val <- lfm_art[lfm_art$name == input$d_lastsm,]$id
# fetch their recommendations: this returns a named vector sorted by similarity
# the names of the items are the artist IDs
arecs <- sort(art_sim[as.character(a_val),], decreasing = TRUE)[1:n_recommended]
# extract the artist IDs and convert to numeric
arecs_IDs <- as.numeric(names(arecs))
# create list of artist names from artist ID's in list
arec_names <- lfm_art[lfm_art$id %in% arecs_IDs,]$name
return(arec_names)
#############################################
} else if (input$Rec_Choices == "tenrecs") {
# Get 10 Artists You May Like based on similar users
# fetch their recommendations
urecs <- sort(as.vector(subset(tenrecs, userID == input$d_userID)[2:11]) )
# create list of artist names from artist ID's in list
rec_names <- subset(lfm_art, id %in% urecs)$name
return(rec_names)
} # end if
},
colnames = FALSE) # end renderTable
}) # end server
shinyApp(ui, server)