Los datos contienen información sobre casi 3 millones de tweets en a lo menos 55 lenguajes diferentes. Cada fila entrega información sobre el tweet como la cuenta asociada, la región desde la que fue generado, su lenguaje, la fecha de creación e incluso una clasificación de las cuentas por categoría general y tipo específico.
Tras abrir el dataset, inicialmente dividido en 13 partes,
files <- list.files(pattern="*.csv")
datasets <- lapply(files, read.csv, sep=",")
dataset <- Reduce(function(df1, df2) merge(df1, df2, all=TRUE), datasets)
obtenemos las distintas categorias y tipos de cuentas:
unique(dataset$account_category)
## [1] Commercial NonEnglish NewsFeed RightTroll Unknown
## [6] HashtagGamer LeftTroll Fearmonger
## 8 Levels: Commercial Fearmonger HashtagGamer LeftTroll ... Unknown
unique(dataset$account_type)
## [1] Commercial Russian news Right ? Hashtager
## [7] Left Koch Arabic Spanish Ebola local
## [13] Ukranian ZAPOROSHIA German French Italian Portuguese
## [19] Uzbek
## 19 Levels: ? Arabic Commercial French German Hashtager Italian ... Uzbek
A modo de exploración inicial, se caracterizaron las frecuencias de palabras en inglés y la inclusión de enlaces externos, además de un estudio de la correlación entre los datos.
Primero se separa el dataset por lenguaje, se extrae el contenido, y se analiza la frecuencia de palabras por lenguaje, excluyendo palabras comúnes que no entregan ninguna información, como pronombres y preposiciones en Inglés, Alemán y Ruso, y las URL, con el siguiente código
Así, se obtienen los siguientes gráficos, mostrando las 25 palabras más comunes para el inglés y el ruso traducidas:
Palabras por frecuencia para el ruso:
Entre las columnas de los datos, se incluyen columnas con el primer, segundo y tercer link incluido en el tweet. Se realiza un análisis de frecuencias para el primer y segundo link en los sets de datos, obteniendo los links con más de 500 menciones en el primer y segundo link. Para el primer enlace, se obtiene el gráfico generado con el siguiente código:
links_freq1_reduced <- list()
data_links1 <- data.frame(tco1_step1 = "", Freq = "")
for(i in 1:13){
links_frequency <- as.data.frame(table(datasets[[i]]$tco1_step1))
names(links_frequency)[1] = "tco1_step1"
links_freq1_reduced[[i]] <- as.data.frame(subset(links_frequency[order(links_frequency$Freq, decreasing = TRUE), ], Freq > 500, select = c("tco1_step1","Freq")))
}
for(j in 1:13){
data_links1 <- merge(data_links1, links_freq1_reduced[[j]], by = "tco1_step1", all = TRUE)
}
## Warning in merge.data.frame(data_links1, links_freq1_reduced[[j]], by
## = "tco1_step1", : column names 'Freq.x', 'Freq.y' are duplicated in the
## result
## Warning in merge.data.frame(data_links1, links_freq1_reduced[[j]], by
## = "tco1_step1", : column names 'Freq.x', 'Freq.y' are duplicated in the
## result
## Warning in merge.data.frame(data_links1, links_freq1_reduced[[j]], by =
## "tco1_step1", : column names 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y' are
## duplicated in the result
## Warning in merge.data.frame(data_links1, links_freq1_reduced[[j]], by =
## "tco1_step1", : column names 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y' are
## duplicated in the result
## Warning in merge.data.frame(data_links1, links_freq1_reduced[[j]], by
## = "tco1_step1", : column names 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y',
## 'Freq.x', 'Freq.y' are duplicated in the result
## Warning in merge.data.frame(data_links1, links_freq1_reduced[[j]], by
## = "tco1_step1", : column names 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y',
## 'Freq.x', 'Freq.y' are duplicated in the result
## Warning in merge.data.frame(data_links1, links_freq1_reduced[[j]], by
## = "tco1_step1", : column names 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y',
## 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y' are duplicated in the result
## Warning in merge.data.frame(data_links1, links_freq1_reduced[[j]], by
## = "tco1_step1", : column names 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y',
## 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y' are duplicated in the result
## Warning in merge.data.frame(data_links1, links_freq1_reduced[[j]], by
## = "tco1_step1", : column names 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y',
## 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y' are duplicated
## in the result
## Warning in merge.data.frame(data_links1, links_freq1_reduced[[j]], by
## = "tco1_step1", : column names 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y',
## 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y' are duplicated
## in the result
## Warning in merge.data.frame(data_links1, links_freq1_reduced[[j]], by
## = "tco1_step1", : column names 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y',
## 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y', 'Freq.x',
## 'Freq.y' are duplicated in the result
data_links1 <- data_links1[-2]
for(k in 2:14){
colnames(data_links1)[k] <- k-1
}
data_links1$`2` <-as.numeric(data_links1$`2`)
data_links1$`4` <- as.numeric(data_links1$`4`)
data_links1$`6` <- as.numeric(data_links1$`6`)
data_links1$`8` <- as.numeric(data_links1$`8`)
frequencies_1 <- rowSums(data_links1[-1], na.rm = TRUE)
data_links_freq <- data.frame(data_links1$tco1_step1,frequencies_1)
data_links_freq <- data_links_freq[-1,]
ggplot(data_links_freq) +
geom_bar(aes(x = data_links_freq$data_links1.tco1_step1, y = data_links_freq$frequencies_1), stat = "identity") +
coord_flip() +
ggtitle("Frecuencia de primeros links en tweets") +
xlab("Link") + ylab("Frecuencia")
Mientras que para el segundo link se obtiene lo siguiente:
links_freq2_reduced <- list()
data_links2 <- data.frame(tco2_step1 = "", Freq = "")
for(i in 1:13){
links_frequency <- as.data.frame(table(datasets[[i]]$tco2_step1))
names(links_frequency)[1] = "tco2_step1"
links_freq2_reduced[[i]] <- as.data.frame(subset(links_frequency[order(links_frequency$Freq, decreasing = TRUE), ], Freq > 100, select = c("tco2_step1","Freq")))
}
for(j in 1:13){
data_links2 <- merge(data_links2, links_freq2_reduced[[j]], by = "tco2_step1", all = TRUE)
}
## Warning in merge.data.frame(data_links2, links_freq2_reduced[[j]], by
## = "tco2_step1", : column names 'Freq.x', 'Freq.y' are duplicated in the
## result
## Warning in merge.data.frame(data_links2, links_freq2_reduced[[j]], by
## = "tco2_step1", : column names 'Freq.x', 'Freq.y' are duplicated in the
## result
## Warning in merge.data.frame(data_links2, links_freq2_reduced[[j]], by =
## "tco2_step1", : column names 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y' are
## duplicated in the result
## Warning in merge.data.frame(data_links2, links_freq2_reduced[[j]], by =
## "tco2_step1", : column names 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y' are
## duplicated in the result
## Warning in merge.data.frame(data_links2, links_freq2_reduced[[j]], by
## = "tco2_step1", : column names 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y',
## 'Freq.x', 'Freq.y' are duplicated in the result
## Warning in merge.data.frame(data_links2, links_freq2_reduced[[j]], by
## = "tco2_step1", : column names 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y',
## 'Freq.x', 'Freq.y' are duplicated in the result
## Warning in merge.data.frame(data_links2, links_freq2_reduced[[j]], by
## = "tco2_step1", : column names 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y',
## 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y' are duplicated in the result
## Warning in merge.data.frame(data_links2, links_freq2_reduced[[j]], by
## = "tco2_step1", : column names 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y',
## 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y' are duplicated in the result
## Warning in merge.data.frame(data_links2, links_freq2_reduced[[j]], by
## = "tco2_step1", : column names 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y',
## 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y' are duplicated
## in the result
## Warning in merge.data.frame(data_links2, links_freq2_reduced[[j]], by
## = "tco2_step1", : column names 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y',
## 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y' are duplicated
## in the result
## Warning in merge.data.frame(data_links2, links_freq2_reduced[[j]], by
## = "tco2_step1", : column names 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y',
## 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y', 'Freq.x', 'Freq.y', 'Freq.x',
## 'Freq.y' are duplicated in the result
data_links2 <- data_links2[-2]
for(k in 2:14){
colnames(data_links2)[k] <- k-1
}
data_links2$`2` <-as.numeric(data_links2$`2`)
data_links2$`4` <- as.numeric(data_links2$`4`)
data_links2$`6` <- as.numeric(data_links2$`6`)
data_links2$`8` <- as.numeric(data_links2$`8`)
frequencies_2 <- rowSums(data_links2[-1], na.rm = TRUE)
data_links_freq2 <- data.frame(data_links2$tco2_step1,frequencies_2)
data_links_freq2 <- data_links_freq2[-1, ]
ggplot(data_links_freq2) +
geom_bar(aes(x = data_links_freq2$data_links2.tco2_step1, y = data_links_freq2$frequencies_2), stat = "identity") +
coord_flip() +
ggtitle("Frecuencia de segundos links en tweets") +
xlab("Link") + ylab("Frecuencia")
Se realiza una exploración básica de los datos, como la distribución de las categorías de cuentas, donde se encuentra que la cantidad de cuentas de la categoría RightTroll es mayor a las de la categorías LeftTroll, por ejemplo.
ggplot(dataset %>% count(account_category)) +
geom_bar(aes(x = account_category, y = n), stat = "identity") +
ylab("Cantidad")
Para los tipos de cuenta se encuentra un dominio de los tipos Right y Russian dentro del número de tweets,
ggplot(dataset %>% count(account_type), aes(x = reorder(account_type, n), y = n)) +
geom_bar(stat = "identity") +
coord_flip() +
ylab("Cantidad")
mientras que para cuentas individuales hay algunas cuentas que dominan en la actividad,
ggplot(dataset %>% count(author) %>% filter(n>20000), aes(x = reorder(author, n), y = n)) +
geom_bar(stat = "identity") +
coord_flip() +
ylab("Cantidad") + xlab("Autor")
y para las regiones de origen, Estados Unidos es sin duda el país dominante.
ggplot(dataset %>% count(region), aes(x = reorder(region, n), y = n)) +
geom_bar(stat = "identity") +
coord_flip() +
ylab("Cantidad") + xlab("Región")
Para las proporciones de lenguajes, los tres lenguajes dominantes son el ingles, el ruso y el alemán, como se muestra en el gráfico a continuación:
ggplot(dataset %>% count(language) %>% filter(n>1000), aes(x = reorder(language, n), y = n)) +
geom_bar(stat = "identity") +
coord_flip() +
ylab("Cantidad")
La distribución de seguidores y seguidos se estudia usando un Boxplot, donde los puntos negros representan a los outliers, que tienen un valor significativamente mas alto que la mayoría de los datos.
mxfr <- aggregate(dataset$followers, by=list(dataset$author), FUN = max) %>%
rename(author = Group.1, max_followers = x)
mxfg <- aggregate(dataset$following, by=list(dataset$author), FUN = max) %>%
rename(author = Group.1, max_following = x)
mx <- melt(merge(mxfr, mxfg, by=c("author")), id = c("author"))
ggplot(mx %>% filter(value < 7500), aes(x=variable, y=value)) +
geom_boxplot() +
ylab("Cantidad")
Y finalmente se puede observar la distribución de la proporción entre retweets y quotes de cada autor.
ct <- rename(dataset %>% count(author), total = n)
cr <- rename(dataset %>% filter(post_type != "") %>% count(author), retweet_or_quote = n)
cj <- merge(ct, cr, by = c("author"))
ratio <- data.frame(author = cj$author, ratio = (cj$retweet_or_quote/cj$total) , value = "tweets")
ggplot(ratio, aes(x= value, y = ratio)) +
geom_boxplot() +
ylab("Ratio retweets & quotes to total tweets")
Para el tema central, se elige estudiar a los elementos que determinan la popularidad de una cuenta o de un tweet en específico. Como el dataset presenta métricas de popularidad, como seguidores o retweets, se desea averiguar si es posible encontrar alguna correlación entre estas métricas y otras propiedades de un tweet o una cuenta, como las palabras usadas, el tono usado, los links incluidos, etc. De manera preliminar, se podría construir un clasificador para los distintos niveles de popularidad o de “Impacto” de un tweet, medida con una métrica aún por determinar, que puede depender tanto de los retweet asociados, como de otros factores como la fecha y la inlcusión de links. También se debe notar que resultaría útil saber exactamente que factores son los que determinan el impacto de un tweet o de una serie de tweets, por lo que sería conveniente hacer un algoritmo que permita conocer los criterios de clasificación, como un arbol de decisión.