I learned a neat trick today. One of those things that once you learn it, you wonder how/why you were so long without it.
I've been working on revising my thesis to try to publish it as a few papers. Because it's such a long paper, I have a 'thesis.tex' file, which is basically a bunch of include statements, to include each of the chapters. As I'm editing it, I open each chapter in a tab in vim, and until today, whenever I wanted to recompile the PDF, I would move to the 'thesis.tex' tab and recompile from there.
So, today I found out that you can set up a .tex file as a "main" file, so that when you '\ll' to compile your .tex code, it will compile that file, instead of the file you're currently looking at.
Instructions:
http://vim-latex.sourceforge.net/documentation/latex-suite/latex-project.html#latex-project-example
Friday, October 17, 2014
Friday, September 5, 2014
Importing Edgelists into RSiena
So, importing data into RSiena is a bit of a pain. The GUI has some support for importing Pajek files, for example, but I've been working mostly from the command line, and with .R files, which are what the manual covers.
For my current project, I have CSV files in a very common edgelist format, something like -
I think it should be simple to import these into RSiena, but it isn't.
RSiena accepts either adjacency matrices - which are matrices with a 0 or 1 in each spot, for each node - or sparse matrices. These are similar to edgelists, but they have to be in the dgTMatrix class. As you can tell by reading the documentation, it's not exactly obvious how to get the data into that format.
I started by trying the Matrix() function, then I found the sparseMatrix() function. I realized that weight didn't matter, so I simply ignored the weight column. This creates a sparse matrix of the type "ngCMatrix", which is a "pattern matrix", and can't be coerced to a dgTMatrix.
So, eventually, I ended up creating a new weight column, with everything set to 1, and reset to 1 if there are duplicate entries in the data.
My current code is below:
For my current project, I have CSV files in a very common edgelist format, something like -
sourceID,receiverID,weight,wave
I think it should be simple to import these into RSiena, but it isn't.
RSiena accepts either adjacency matrices - which are matrices with a 0 or 1 in each spot, for each node - or sparse matrices. These are similar to edgelists, but they have to be in the dgTMatrix class. As you can tell by reading the documentation, it's not exactly obvious how to get the data into that format.
I started by trying the Matrix() function, then I found the sparseMatrix() function. I realized that weight didn't matter, so I simply ignored the weight column. This creates a sparse matrix of the type "ngCMatrix", which is a "pattern matrix", and can't be coerced to a dgTMatrix.
So, eventually, I ended up creating a new weight column, with everything set to 1, and reset to 1 if there are duplicate entries in the data.
My current code is below:
edgeListToAdj <- function(x, waveID){
# Remove entries who are not connect to anyone (NomineeID == 0), and not the
# current wave
tempNet <- x[x$NomineeID > 0 & x$NomineeID <= nodeCount & x$Wave == waveID,]
# Create a binary column for weights (since RSiena doesn't use weights).
tempNet$Weight <- 1
# Convert network obejct to adjacency matrix
adjacencyMat <- sparseMatrix(tempNet$NomineeID, tempNet$RespondentID, x=tempNet$Weight, dims=c(nodeCount,nodeCount))
# If any items appear more than once, re-binarize them.
# Yes, binarize is a real word.
adjacencyMat[adjacencyMat > 1] <- 1
# Convert to a dgTMatrix, since this is what RSiena expects
return(as(adjacencyMat, "dgTMatrix"))
}
createNetwork <- function(fileName, numWaves) {
print(fileName)
# Convert CSV file to data frame
netDF <- as.data.frame(read.csv(fileName))
# Create an array of adjacency networks
net <- lapply(1:numWaves, function(x) edgeListToAdj(netDF, x))
# Change this into an RSiena network
RSienaObj <- sienaDependent(net)
return(RSienaObj)
}
Tuesday, July 15, 2014
Thesis Accepted
My thesis is defended, edited, and accepted.
It's online at
https://www.academia.edu/7544796/ONLINE_NATURALIZATION_EVOLVING_ROLES_IN_ONLINE_KNOWLEDGE_PRODUCTION_COMMUNITIES
I'm pretty proud of how it turned out. I didn't get all of the results I was hoping for, but that's research.
It's online at
https://www.academia.edu/7544796/ONLINE_NATURALIZATION_EVOLVING_ROLES_IN_ONLINE_KNOWLEDGE_PRODUCTION_COMMUNITIES
I'm pretty proud of how it turned out. I didn't get all of the results I was hoping for, but that's research.
Thursday, July 3, 2014
Thesis Defended!
I haven't kept up on this blog as much as I should have, but my thesis is done and defended!
Saturday, April 12, 2014
An Analysis of Interactions on the Boston Subway
I made my first ever visit to Boston this past week, and while I was there, I was able to put together a small research project. On a subway ride, I carefully noted each of the interactions between the 50 riders in the train car I was in, during a 15 minute ride. Edge weight represents number of minutes spent talking to each other.
Nodes are colored based on degree centrality, sized based on eigenvector centrality, and spaced with Fruchterman-Reingold in Gephi.
Nodes are colored based on degree centrality, sized based on eigenvector centrality, and spaced with Fruchterman-Reingold in Gephi.
So far, the research is merely descriptive, but I think some real insights could be made through running an actor-oriented model.
:)
Thursday, April 3, 2014
.vimrc and Dropbox
If you have used vim for very long, you have almost certainly made some modifications to your .vimrc file - this is the file that stores configurations for how vim does things like tabs, syntax highlighting, etc.
If you use more than one computer, I highly recommend keeping your .vimrc file on the cloud. It's incredibly simple, and provides for a consistent experience across computers.
This Stack Overflow post gives simple instructions on how to do this.
If you use more than one computer, I highly recommend keeping your .vimrc file on the cloud. It's incredibly simple, and provides for a consistent experience across computers.
This Stack Overflow post gives simple instructions on how to do this.
Saturday, March 29, 2014
Roles Visualization
So, I thanks to some help from the very kind BrodieG on Stack Overflow, I was finally able to get some visualizations of the way that roles change over time. I am using the following code (as you can see, I tried to learn how to do melting and reshaping, then kind of gave up that hope - maybe another time).


There are some interesting things going on here, but no clear movement into the central-type role (Role 1).
library(reshape2)
library(ggplot2)
#clusters.mlt <- melt(clusters, id.vars="id")
#clusters.agg <- aggregate(. ~ id + variable, clusters.mlt, sum)
# The minimum number of times a user has to be in a given group in order to
# be shown in the graph for that group
minMonths = 2
makeGraph <- function(clusters){
clus1 <- apply(clusters, 2, function(x) {sum(x=='1', na.rm=TRUE)})
clus2 <- apply(clusters, 2, function(x) {sum(x=='2', na.rm=TRUE)})
clus3 <- apply(clusters, 2, function(x) {sum(x=='3', na.rm=TRUE)})
clus0 <- apply(clusters, 2, function(x) {sum(x=='0', na.rm=TRUE)})
clusters2 <- data.frame(clus0, clus1, clus2, clus3)
c2 <- t(clusters2)
c3 <- as.data.frame(c2)
c3$id = c('Low Activity Cluster', 'Cluster 1', 'Cluster 2', 'Cluster 3')
c3 <- c3[order(c3$'id'),]
return(ggplot(melt(c3, id.vars="id")) +
geom_area(aes(x=variable, y=value, fill=id, group=id), position="fill"))
}
#print(ggplot(clusters.mlt) +
# stat_summary(aes(x=variable, y=value, fill=id, group=id), fun.y=sum, position="fill", geom="area"))
# Stats for just those who were in each group
clusterDF <- as.data.frame(read.csv('clustersByID.csv'))
ggsave(file="../Results/allUsers.png", plot=makeGraph(clusterDF))
cl1 <- clusterDF[apply(clusterDF, 1, function(x) {sum(x[2:76] == "1", na.rm=TRUE) >= minMonths}),]
ggsave("../Results/Role1_2+.png", makeGraph(cl1))
And this is what the code produces (some new colors would probably be a good thing to work on next!)


There are some interesting things going on here, but no clear movement into the central-type role (Role 1).
Subscribe to:
Posts (Atom)
