From a32447a27b2897f812896ea1f9eee55bbd151349 Mon Sep 17 00:00:00 2001 From: mxmehl Date: Tue, 24 Feb 2015 22:03:47 +0100 Subject: [PATCH] splitting files, adding entropy test --- ...ecomp-scraping.R => issuecomp-1-scraping.R | 0 ...ecomp-analysis.R => issuecomp-2-analysis.R | 82 ++--------- issuecomp-3-calc.R | 130 ++++++++++++++++++ issues.RData | Bin 8825 -> 11032 bytes 4 files changed, 144 insertions(+), 68 deletions(-) rename issuecomp-scraping.R => issuecomp-1-scraping.R (100%) rename issuecomp-analysis.R => issuecomp-2-analysis.R (67%) create mode 100644 issuecomp-3-calc.R diff --git a/issuecomp-scraping.R b/issuecomp-1-scraping.R similarity index 100% rename from issuecomp-scraping.R rename to issuecomp-1-scraping.R diff --git a/issuecomp-analysis.R b/issuecomp-2-analysis.R similarity index 67% rename from issuecomp-analysis.R rename to issuecomp-2-analysis.R index b19c48b..4033d27 100644 --- a/issuecomp-analysis.R +++ b/issuecomp-2-analysis.R @@ -55,7 +55,7 @@ foreach(d = 1:nrow(issues), .packages = c("stringr"), .combine=rbind) %dopar% { tweets_curday <- tweets[tweets[, "created_at"] == curdate, ] for(t in 1:nrow(tweets_curday)){ -# cat(paste("Starting tweet", t, "of",as.character(curdate),"\n"), file="issuecomp-analysis.log", append=TRUE) + # cat(paste("Starting tweet", t, "of",as.character(curdate),"\n"), file="issuecomp-analysis.log", append=TRUE) # Select tweet's text, make it lowercase and remove hashtag indicators (#) curtext <- as.character(tweets_curday$text[t]) curtext <- str_replace_all(curtext, "#", "") @@ -67,7 +67,7 @@ foreach(d = 1:nrow(issues), .packages = c("stringr"), .combine=rbind) %dopar% { curissue <- issueheads[i] curtags <- as.character(issuelist[[curissue]]) curfile <- str_c(id_folder,"/",curissue,".csv") - + # Now test all tags of a single issue for(s in 1:length(curtags)) { curtag <- curtags[s] @@ -93,7 +93,7 @@ foreach(d = 1:nrow(issues), .packages = c("stringr"), .combine=rbind) %dopar% { } else { curdistance <- 1 } - + # Match current tweet with tag. If >= 5 letters allow 1 changed letter, if >=8 letters allow also 1 (Levenshtein distance) tags_found <- NULL # Match the tweet with each variation of tagexpand @@ -104,19 +104,19 @@ foreach(d = 1:nrow(issues), .packages = c("stringr"), .combine=rbind) %dopar% { curtag <- curtag[1] if(tags_found == TRUE) { -# # Raise number of findings on this day for this issue by 1 -# issues[d,curissue] <- issues[d,curissue] + 1 -# -# # Add issue and first matched tag of tweet to tweets-DF -# oldissue <- tweets[tweets[, "id_str"] == curid, "issue"] -# tweets[tweets[, "id_str"] == curid, "issue"] <- str_c(oldissue, curissue, ";") -# oldtag <- tweets[tweets[, "id_str"] == curid, "tags"] -# tweets[tweets[, "id_str"] == curid, "tags"] <- str_c(oldtag, curtag, ";") + # # Raise number of findings on this day for this issue by 1 + # issues[d,curissue] <- issues[d,curissue] + 1 + # + # # Add issue and first matched tag of tweet to tweets-DF + # oldissue <- tweets[tweets[, "id_str"] == curid, "issue"] + # tweets[tweets[, "id_str"] == curid, "issue"] <- str_c(oldissue, curissue, ";") + # oldtag <- tweets[tweets[, "id_str"] == curid, "tags"] + # tweets[tweets[, "id_str"] == curid, "tags"] <- str_c(oldtag, curtag, ";") # Add information to file for function viewPatternMatching write(str_c(curdate,";\"",curid,"\";",curissue,";",curtag), curfile, append = TRUE) -# cat(paste("Match!\n"), file="issuecomp-analysis.log", append=TRUE) -# data.frame(date=curdate, issue=curissue) + # cat(paste("Match!\n"), file="issuecomp-analysis.log", append=TRUE) + # data.frame(date=curdate, issue=curissue) break # next issue, no more tags from same issue } else { @@ -182,60 +182,6 @@ for(r in 1:nrow(results)) { # SAVING ------------------------------------------------------------------ save(tweets, file="tweets_tagged.RData") +save(issues, file="issues.RData") - -# SOME TESTS -------------------------------------------------------------- - -stats <- data.frame(date=drange) -stats$tpd <- 0 - -# Total number of tweets per day over time -for(r in 1:length(drange)) { - stats$tpd[r] <- length(tweets[tweets[, "created_at"] == drange[r], "id_str"]) -} - -stats_melt <- melt(stats, id="date") -g1 <- ggplot(data = stats_melt, aes(x=date,y=value,colour=variable, group=variable)) + - geom_line() + - geom_smooth(size=1,formula = y ~ x, method="loess", se=FALSE, color=1) -g1 - -rm(g1, r) - - -# Show party percentage of twitter users -acc_parties <- data.frame(party = c("cducsu", "spd", "linke", "gruene")) -acc_parties$btw13 <- c(49.3, 30.6, 10.1, 10.0) # seats of party / 631 seats -acc_parties$twitter <- 0 -for(p in 1:nrow(acc_parties)) { - acc_parties$twitter[p] <- round(nrow(acc_df[acc_df$party == as.character(acc_parties$party[p]), ]) / 280 * 100) -} -pie(acc_parties$btw13, col=c("black", "red", "purple", "green"), labels = c("CDU/CSU", "SPD", "Die LINKE", "Bündnis 90/Grüne"), clockwise = T, - main = "Seats of parties in the parliament") -pie(acc_parties$twitter, col=c("black", "red", "purple", "green"), labels = c("CDU/CSU", "SPD", "Die LINKE", "Bündnis 90/Grüne"), clockwise = T, - main = "Percentage of parties' MdBs of all Twitter accounts") - -rm(acc_parties, p) - - -# VISUALS ----------------------------------------------------------------- - - -# Level: days -issues_melt <- melt(issues,id="date") -ggplot(issues_melt,aes(x=date,y=value,colour=variable,group=variable)) + geom_line(size=1) -ggplot(issues_melt,aes(x=date,y=value,colour=variable,group=variable)) + geom_smooth(size=1,method="loess",formula = y ~ x, se=FALSE) - - - -# POSSIBLY USEFUL CODE ---------------------------------------------------- - -# Limits of list -length(issuelist) -length(issuelist[[2]]) - -# Select all tweets from current day in drange -tweets_curday <- tweets[tweets[, "created_at"] == drange[5], ] -# Is column a issue counting column? -str_detect(names(issues[2]), "^issue") \ No newline at end of file diff --git a/issuecomp-3-calc.R b/issuecomp-3-calc.R new file mode 100644 index 0000000..c6535ed --- /dev/null +++ b/issuecomp-3-calc.R @@ -0,0 +1,130 @@ +require(stringr) +require(reshape2) +require(ggplot2) +require(vars) + +# Create dataframes with only non-sensational (i) and sensational (s) issue columns +drop_s <- which(str_detect(names(issues), "^s")) +drop_i <- which(str_detect(names(issues), "^i")) +issues_i <- issues[,-drop_s] +issues_s <- issues[,-drop_i] + +# # +# ENTROPY +# # +# Entropy non-sensational issues +issues_i$total <- rowSums(issues_i[2:ncol(issues_i)]) +issues_i$entropy <- 0 + +for(r in 1:nrow(issues_i)) { + curtotal <- as.numeric(issues_i$total[r]) + curp <- 0 + for(c in 2:ncol(issues_i)) { + curcount <- as.numeric(issues_i[r,c]) + curp[c] <- curcount / curtotal + } + curp <- curp [2:length(curp)-2] + curdrop <- which(curp==0) + curp <- curp[-curdrop] + issues_i$entropy[r] <- sum(-1 * curp * log(curp)) +} + +# Entropy sensational issues +issues_s$total <- rowSums(issues_s[2:ncol(issues_s)]) +issues_s$entropy <- 0 + +for(r in 1:nrow(issues_s)) { + curtotal <- as.numeric(issues_s$total[r]) + curp <- 0 + for(c in 2:ncol(issues_s)) { + curcount <- as.numeric(issues_s[r,c]) + curp[c] <- curcount / curtotal + } + curp <- curp [2:length(curp)-2] + curdrop <- which(curp==0) + curp <- curp[-curdrop] + issues_s$entropy[r] <- sum(-1 * curp * log(curp)) +} + + +# Compare total tweets vs. total issue findings +stats_total <- data.frame(date=drange) +stats_total$tpd <- 0 +stats_total$ipd <- issues_i$total +stats_total$spd <- issues_s$total +# Total number of tweets per day over time +for(r in 1:length(drange)) { + stats_total$tpd[r] <- length(tweets[tweets[, "created_at"] == drange[r], "id_str"]) +} + +stats_melt <- melt(stats_total, id="date") +g1 <- ggplot(data = stats_melt, aes(x=date,y=value,colour=variable, group=variable)) + + geom_line()+ + geom_smooth(size=1,formula = y ~ x, method="loess", se=FALSE, color=1) +g1 + +# Visuals for entropy in time series +stats_entropy <- data.frame(date=drange) +stats_entropy$entropy <- issues_i$entropy + +stats_entropy <- melt(stats_entropy, id="date") + +g1 <- ggplot(data = stats_entropy, aes(x=date,y=value,colour=variable, group=variable)) + + geom_line() + + geom_smooth(size=1,formula = y ~ x, method="loess", se=FALSE, color=1) +g1 + +# SOME TESTS -------------------------------------------------------------- + +stats <- data.frame(date=drange) +stats$tpd <- 0 + +# Total number of tweets per day over time +for(r in 1:length(drange)) { + stats$tpd[r] <- length(tweets[tweets[, "created_at"] == drange[r], "id_str"]) +} + +stats_melt <- melt(stats, id="date") +g1 <- ggplot(data = stats_melt, aes(x=date,y=value,colour=variable, group=variable)) + + geom_line() + + geom_smooth(size=1,formula = y ~ x, method="loess", se=FALSE, color=1) +g1 + +rm(g1, r) + + +# Show party percentage of twitter users +acc_parties <- data.frame(party = c("cducsu", "spd", "linke", "gruene")) +acc_parties$btw13 <- c(49.3, 30.6, 10.1, 10.0) # seats of party / 631 seats +acc_parties$twitter <- 0 +for(p in 1:nrow(acc_parties)) { + acc_parties$twitter[p] <- round(nrow(acc_df[acc_df$party == as.character(acc_parties$party[p]), ]) / 280 * 100) +} +pie(acc_parties$btw13, col=c("black", "red", "purple", "green"), labels = c("CDU/CSU", "SPD", "Die LINKE", "Bündnis 90/Grüne"), clockwise = T, + main = "Seats of parties in the parliament") +pie(acc_parties$twitter, col=c("black", "red", "purple", "green"), labels = c("CDU/CSU", "SPD", "Die LINKE", "Bündnis 90/Grüne"), clockwise = T, + main = "Percentage of parties' MdBs of all Twitter accounts") + +rm(acc_parties, p) + + +# VISUALS ----------------------------------------------------------------- + + +# Level: days +issues_melt <- melt(issues,id="date") +ggplot(issues_melt,aes(x=date,y=value,colour=variable,group=variable)) + geom_line(size=1) +ggplot(issues_melt,aes(x=date,y=value,colour=variable,group=variable)) + geom_smooth(size=1,method="loess",formula = y ~ x, se=FALSE) + + + +# POSSIBLY USEFUL CODE ---------------------------------------------------- + +# Limits of list +length(issuelist) +length(issuelist[[2]]) + +# Select all tweets from current day in drange +tweets_curday <- tweets[tweets[, "created_at"] == drange[5], ] +# Is column a issue counting column? +str_detect(names(issues[2]), "^issue") \ No newline at end of file diff --git a/issues.RData b/issues.RData index 309866c9417b777dbc9e99ee9b229d6068edb295..41909d364a3db8b7644ea8a0d7edceb4a4a9a3c5 100644 GIT binary patch literal 11032 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 literal 8825 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