-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathAnalisis Github.Rmd
More file actions
279 lines (205 loc) · 9.6 KB
/
Analisis Github.Rmd
File metadata and controls
279 lines (205 loc) · 9.6 KB
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
276
277
278
279
---
title: "Análisis developers github"
output: html_document
---
Vamos a analizar los developers registrados en github más populares para los lenguajes R y Python
con el objetivo de estar informados de quiénes son los máximos influyentes en ambos lenguajes.
Vamos a suponer que para ser un trending developer en R y/o Python se han de tener al menos 300 followers y al menos 1 repositorio creado.
***Autenticarse en github para lanzar el script ya que hay limitaciones en el uso de la API:***
* https://developer.github.com/v3/#rate-limiting
* ***For requests using Basic Authentication or OAuth, you can make up to 5,000 requests per hour.***
* ***For unauthenticated requests, the rate limit allows you to make up to 60 requests per hour.***
#### Indicar credenciales de usuario de github para poder ejecutar correctamente todo el script
```{r}
user_github = '________'
pass_github = '________'
```
Opciones para la conexión con la API a través de RCurl
```{r}
curl.opts = list(userpwd = paste(user_github, pass_github, sep=':'), ssl.verifypeer = FALSE,
useragent = 'curl', httpauth = 1L)
```
## Carga Librerías
```{r message=FALSE, warning=FALSE, results=FALSE}
library(RCurl)
library(rjson)
library(plyr)
library(ggplot2)
library(plotly)
```
## Constantes
```{r}
followers <- 300
repos <- 1
```
##Definición de funciones
**pagination**
* Devuelve el resultado de la query de url_paginar ya que la API muestra un máximo de 100 resultados por página
```{r}
pagination <- function(url_paginar, num_page){
nueva_pagina <- gsub('&page=(\\d+)', paste('&page=', as.character(num_page), sep=''), url_paginar)
results_page <- fromJSON(getURL(nueva_pagina, .opts = curl.opts))
return(results_page)
}
```
**top_developers_by_language**
* Args:
+ programming_language: Lenguaje de programación por el que buscar
+ min_followers: Condición para la query como mínimo de followers
+ min_repos : Condición para la query como mínimo de repositorios
* Return:
+ Devuelve lista ordenada por numero de followers con los top developers por el programming_language
* API:
+ https://developer.github.com/v3/search/#search-code
```{r}
top_developers_by_language <- function(programming_language, min_followers, min_repos){
type_user <- 'User'
page <- 1
results_per_page <- 100
url <- sprintf('https://api.github.com/search/users?q=language:%s+repos:>%i+followers:>%i+sort:followers+type:%s&per_page=%i&page=%i', programming_language, min_repos, min_followers, type_user, results_per_page, page)
top_developers <- fromJSON(getURL(url, .opts = curl.opts))
#Número total de páginas para obtener todos los developers
total_pages <- ceiling(top_developers$total_count / results_per_page)
if (total_pages > 1){
# Append de los nuevos items en list$items
top_developers$items <- c(top_developers$items,
do.call('c', lapply(c(2:total_pages), function(i){pagination(url, i)$items})))
}
return(top_developers$items)
}
```
**followers_by_developer**
* Args:
+ nick: username del developer
+ min_followers: Condición para la query como mínimo de followers
+ min_repos : Condición para la query como mínimo de repositorios
* Return:
+ Devuelve el número de followers del developer
* API:
+ https://developer.github.com/v3/users/followers/#list-followers-of-a-user
```{r}
followers_by_developer <- function(username_developer){
page <- 1
results_per_page <- 100
number_followers <- 0
url <- sprintf('https://api.github.com/users/%s/followers?per_page=%i&page=%i',
username_developer, results_per_page, page)
repeat{
result_query <- pagination(url,page)
if(length(result_query) == 0){
break
} else {
page <- page + 1
number_followers <- number_followers + length(result_query)
}
}
return(number_followers)
}
```
**repositories_by_developer**
* Args:
+ developer: username del developer
+ programming_language: Lenguaje de programación del developer por el que buscamos
* Return:
+ Devuelve lista con el username del developer y el nombre, descripción, url y stars de cada uno de los repositorios del propio developer filtrados por el programming_language indicado
* API:
+ https://developer.github.com/v3/repos/#list-user-repositories
```{r}
repositories_by_developer <- function(username, programming_language){
url <- sprintf('https://api.github.com/users/%s/repos', username)
repos <- fromJSON(getURL(url, .opts = curl.opts))
repos <- sapply(repos, function(element){
if (!is.null(element$language) && element$language == programming_language){
return(list(username, programming_language, element$name,
element$description, element$html_url, element$stargazers_count))
}})
return(repos[lapply(repos,length)>0])
}
```
## Preparación de datos
Creamos un dataset para cada lenguaje añadiendo una columna para identificar el lenguaje con el developer
Dataframe top developers de Python
```{r}
top_developers_Python <- top_developers_by_language('python', followers, repos)
df_top_developers_Python <- as.data.frame(do.call('rbind', top_developers_Python))
df_top_developers_Python <- as.data.frame(sapply(df_top_developers_Python, as.character),
stringsAsFactors = FALSE)
df_top_developers_Python$language <- 'Python'
```
Dataframe top developers de R
```{r}
top_developers_R <- top_developers_by_language('R', followers, repos)
df_top_developers_R <- as.data.frame(do.call('rbind', top_developers_R))
df_top_developers_R<- as.data.frame(sapply(df_top_developers_R, as.character),
stringsAsFactors = FALSE)
df_top_developers_R$language <- 'R'
```
Join ambos dataframes por el username
```{r}
df_devs <- join(df_top_developers_Python, df_top_developers_R, by='login', type = 'full')
```
Eliminar filas que no interesan, renombramos columnas y cambiamos el orden de las mismas
```{r}
df_devs <- df_devs[, c('login', 'html_url', 'followers_url','repos_url', 'language')]
names(df_devs) <- c('user_name', 'user_page', 'followers_url', 'repos_url', 'language')
df_devs <- df_devs[, c('language', 'user_name', 'user_page', 'followers_url', 'repos_url')]
```
Búsqueda del número de followers de cada developer y se añade en una nueva columna
**Este paso tarda varios minutos**
```{r cache=TRUE}
df_devs$num_followers <- sapply(df_devs$user_name, followers_by_developer)
```
Ordenamos el dataframe por num_followers
```{r}
df_devs <- df_devs[order(df_devs$num_followers, decreasing = TRUE), ]
```
Obtenemos la lista de repositorios de cada developer y creamos un dataframe con los repos más
populares de los developers del dataframe df_devs creado anteriormente
```{r cache=TRUE}
repositories <- mapply(repositories_by_developer, df_devs$user_name, df_devs$language)
repositories <- unlist(repositories, recursive = FALSE)
repositories <- as.data.frame(do.call('rbind', repositories))
#Renombramos filas y columnas
rownames(repositories) <- 1:nrow(repositories)
names(repositories) <- c('user_name', 'language', 'name_repo', 'description_repo',
'url_repo', 'stars_repo')
#Cambiamos tipo de las columnas a character excepto la última (stars_repo) que es tipo integer
repositories <- as.data.frame(sapply(repositories, as.character), stringsAsFactors = FALSE)
repositories$stars_repo <- as.integer(repositories$stars_repo)
```
Ordenamos el dataframe por stars_repo
```{r}
repositories <- repositories[order(repositories$stars_repo, decreasing = TRUE), ]
```
## Insights
### Top 10 developers agrupados por lenguaje de programación
```{r}
developers_top_10 <- df_devs[1:10,]
ggplot(data=developers_top_10, aes(x=reorder(user_name, num_followers), y=num_followers, fill=language)) +
geom_bar(stat="identity") + xlab("Developers") + ylab("Followers") +
ggtitle("Top 10 developers by followers") + coord_flip()
```

### Top 10 repositorios agrupados por developer
```{r fig.width=12}
repositories_top_10 <- repositories[1:10,]
ggplot(data=repositories_top_10, aes(x=reorder(name_repo, stars_repo), y=stars_repo, fill=user_name)) +
geom_bar(stat="identity") + xlab("Repositories") + ylab("Stars") +
ggtitle("Top 10 repositories by stars of top developers") +
theme(text = element_text(size=12)) + coord_flip()
```

TODO:
Add url links to the charts to jump directly to the developer/repository webpage
### Bibliografía:
* https://developer.github.com/v3/search/#search-users
* https://stackoverflow.com/questions/15415485/concatenate-list-of-lists-in-r
* https://stackoverflow.com/questions/12344982/r-lapply-statement-with-index
* https://stackoverflow.com/questions/13169305/httr-github-api-callback-url-issues
* https://stackoverflow.com/questions/12302941/convert-curl-code-into-r-via-the-rcurl-package
* https://stackoverflow.com/questions/16121463/using-rcurl-httr-for-github-basic-authorization
* http://www.r-bloggers.com/ggplot2-cheatsheet-for-barplots/
* http://www.cookbook-r.com/Graphs/Bar_and_line_graphs_(ggplot2)/
* https://stackoverflow.com/questions/6455088/how-to-put-labels-over-geom-bar-in-r-with-ggplot2
* https://stackoverflow.com/questions/10941225/horizontal-barplot-in-ggplot2
* http://www.cookbook-r.com/Graphs/Facets_(ggplot2)/#facet_grid