]> code.communitydata.science - opensym2017_postmortem.git/blob - opensym2017_postmortem.Rmd
added material to .gitignore file
[opensym2017_postmortem.git] / opensym2017_postmortem.Rmd
1 ---
2 title: "OpenSym 2017 Program Postmortem"
3 output: html_document
4 ---
5
6 ```{r setup, include=FALSE}
7 knitr::opts_chunk$set(echo = TRUE)
8 ```
9
10 ```{r, echo=FALSE}
11 library(data.table)
12 library(ggplot2)
13 library(xtable)
14 library(knitr)
15
16 reviews <- read.csv("opensym-reviews-20180113.csv", stringsAsFactors = FALSE)
17 colnames(reviews) <- gsub('_', '.', colnames(reviews))
18 reviews$date <- as.Date(reviews$date)
19 reviews$subreviewer[reviews$subreviewer == ""] <- NA
20 reviews$reviewer[reviews$reviewer == ""] <- NA
21
22 submissions <- read.csv("opensym-submissions-20180113.csv", stringsAsFactors=FALSE)
23 colnames(submissions) <- gsub('_', '.', colnames(submissions))
24
25 authors <- read.csv("opensym-authors-20180113.csv", stringsAsFactors=FALSE)
26 colnames(authors) <- gsub('_', '.', colnames(authors))
27 ```
28
29 ```{r echo=FALSE}
30 crop.scores <- function (sub.id, before=FALSE) {
31   d <- reviews[reviews$sub.id == sub.id,]
32   cut.off <- d[d$label == "Author response", "date"]
33   
34   # reduce it to everything before if we're before
35   if (before) {
36     d <- d[d$date < cut.off,]
37   }
38   
39   d <- d[grep('^Review ', d$label),]
40   
41   # remove duplicates keeping the final score in the zone
42   d <- d[sort.list(d$date, decreasing=TRUE),]
43   d <- d[!duplicated(d$label),]
44   d <- d[sort.list(d$date),]
45
46   return(d)
47 }
48
49 scores.before <- do.call("rbind", lapply(unique(reviews$sub.id), crop.scores, before=TRUE))
50 scores.after <- do.call("rbind", lapply(unique(reviews$sub.id), crop.scores))
51
52 avg.score.df <- function (d) {
53   tbl <- tapply(d$score, d$sub.id, mean)
54   data.frame(sub.id=as.integer(names(tbl)),
55              avg.score=as.numeric(tbl))
56   
57 }
58
59 scores <- merge(avg.score.df(scores.before), avg.score.df(scores.after), by="sub.id", suffixes=c(".before", ".after"))
60 scores$delta <- scores$avg.score.before - scores$avg.score.after
61
62 grid.tmp <- melt(scores, id.vars=c("sub.id"))
63
64 # build table of changes
65 scores$change <- NA
66 scores$change[scores$delta == 0] <- "none"
67 scores$change[scores$delta > 0] <- "decrease"
68 scores$change[scores$delta < 0] <- "increase"
69   
70 # merge in data about submissions
71 scores <-  merge(scores, submissions[,c("sub.id", "type", "result")],
72                  by="sub.id")
73
74 scores$decision <- "Rejected"
75 scores$decision[scores$type == "full paper" & scores$result == "ACCEPT"] <- "Accepted"
76 scores$decision[scores$type == "poster" & scores$result == "ACCEPT"] <- "Poster"
77
78 scores$sub.id <- ordered(scores$sub.id, levels=scores$sub.id[sort.list(scores$avg.score.after)])
79 scores.after$sub.id <- ordered(scores.after$sub.id, levels=levels(scores$sub.id))
80 ```
81
82 The [International Symposium on Open Collaboration](http://www.opensym.org/) (*OpenSym*, formerly *WikiSym*) is the premier academic venue exclusively focused on scholarly research into open collaboration. OpenSym is an [ACM](http://www.acm.org/) conference which means that, like conferences in computer science, it's really more like a journal that gets published once a year than it is like most social science conferences. The "journal", in this case, is called the *Proceedings of OpenSym* and it consists of all the papers presented there. Papers that are published in the proceedings are not typically published elsewhere.
83
84 Along with [Claudia Müller-Birn](https://www.clmb.de/) from the [Freie Universtät Berlin](http://www.fu-berlin.de/), I served as the *Program Chair* for OpenSym 2017. For the social scientists reading this, the role of program chair is similar to being an editor for a journal. My job was *not* to organize keynotes or logistics at the conference—that is the job of the General Chair.  Indeed, in the end I didn't even attend the conference! Along with Claudia, my role as Program Chair was to recruit submissions, recruit reviewers, coordinate and manage the review process, make final decisions on papers, and ensure that everything makes it into the published proceedings in good shape.
85
86 In OpenSym 2017, we made several changes to the way the conference has been run:
87
88 * In previous years, OpenSym had tracks on topics like free/open source software, wikis, open innovation, open education, and so on. In 2017, **we used a single track model**.
89 * Because we eliminated tracks, we also eliminated track-level chairs. Instead, **we appointed a series of Associate Chairs or ACs**.
90 * **We eliminated page limits and the distinction between full papers and notes**.
91 * **We allowed authors to write rebuttals before reviews were finalized.** Reviewers and ACs were allowed to modify their reviews and decisions based on rebuttals.
92 * To assist in assigning papers to ACs and to reviewers, **we made extensive use of bidding**. This means we had to recruit the pool of reviewers before papers were submitted.
93
94 Although each of these things have been tried in other conferences, all were new to OpenSym.
95
96 # Overview
97
98 ```{r, echo=FALSE, results="asis"}
99 # two papers were originally submitted as posters
100 num.papers.accepted <- table(submissions$result == "ACCEPT" & submissions$type == "full paper")["TRUE"]
101
102 tbl.tmp <- as.data.frame(rbind(
103   list("Papers submitted",
104       nrow(submissions) -2),  # HARD CODED!!
105   list("Papers accepted",
106        num.papers.accepted),
107   list("Acceptance rate", 
108        paste(round(num.papers.accepted / (nrow(submissions) - 2)*100), "%", sep="")),
109   list("Posters submitted", 
110        2), # HARD CODED!!
111   list("Posters presented", 
112        table(submissions$result == "ACCEPT" & submissions$type == "poster")["TRUE"]),
113   list("Associate Chairs",
114        8),
115   list("PC Members",
116        length(na.omit(unique(c(reviews$reviewer, reviews$subreviewer))))),
117   list("Authors",
118        length(unique(authors$author))),
119   list("Author countries",
120        length(unique(authors$country)))
121   ))
122
123 colnames(tbl.tmp) <- c("Statistics", "")
124   
125 kable(tbl.tmp)
126
127 ```
128
129 The program was similar in size to the last 2-3 years in terms of the number of submissions. OpenSym is a small but mature and stable venue for research on open collaboration. This year was also similar, although slightly more competitive, in terms of the conference acceptance rate (`r round(num.papers.accepted / (nrow(submissions) - 2)*100)`%—it had been slightly above 50% in previous years).
130
131 As in recent years, there were more posters accepted than submitted because the PC found that some rejected work, although not ready to be published in the proceedings, was promising and advanced enough to be presented as a poster at the conference. Authors of posters submitted 4-page extended abstracts for their projects which were published in a "*Companion to the Proceedings*.""
132
133 # Topics
134
135 Over the years, OpenSym has established a clear set of niches. Although we eliminated tracks, we asked authors to choose from a set of categories when submitting their work. These categories are similar to the tracks at OpenSym 2016. Interestingly, a number of authors selected more than one category. This would have led to difficult decisions in the old track-based system.
136
137 ```{r topics, echo=FALSE}
138 submissions$topic <- sub(", esp. Wikis and Social Media", '', submissions$topic)
139 submissions$topic.nums <- sapply(strsplit(submissions$topic, ", "), length)
140
141 # create a list of topics
142 topics <- data.frame(topic=unlist(strsplit(submissions$topic, ", ")),
143                      sub.id=unlist(lapply(1:nrow(submissions), 
144                                           function (i) { rep(submissions$sub.id[i], submissions$topic.nums[i]) })))
145
146 # add decisions
147 topics <- merge(topics, scores[,c("sub.id", "decision")], by="sub.id")
148 topics$topic <- factor(topics$topic, levels=names(sort(table(topics$topic))))
149
150 ggplot(data=topics) + aes(x=topic, fill=decision) + 
151   geom_bar() + 
152   scale_y_continuous("Count") + 
153   scale_x_discrete("") +
154   coord_flip() +
155   scale_fill_discrete("Decision") +
156   theme_minimal() +
157   theme(legend.position="bottom", legend.direction = "horizontal")
158 ```
159
160 The figure above shows a breakdown of papers in terms of these categories as well as indicators of how many papers in each group were accepted. Research on FLOSS and Wikimedia/Wikipedia continue to make up a sizable chunk of OpenSym's submissions and publications. That said, these now make up a minority of total submissions. Although Wikipedia and Wikimedia research made up a smaller proportion of the submission pool, it was accepted at a higher rate. Also notable is the fact that 2017 saw an uptick in the number of papers on open innovation. I suspect this was due, at least in part, to work by the General Chair [Lorraine Morgan's](https://www.nuigalway.ie/our-research/people/lorrainemorgan/) involvement (she specializes in that area). Somewhat surprisingly to me, we had a number of submission about Bitcoin and blockchains. These are natural areas of growth for OpenSym but have never been a big part of work in our community in the past.
161
162 # Scores and Reviews
163
164 As in previous years, review was single blind in that reviewers' identities are hidden but authors identities are not. Each papers received between 3 and 4 reviews plus a metareview by the Associate Chair assigned to the paper. Almost all papers received 3 reviews but ACs were encouraged to call in a 4th reviewer at any point in the process.  In addition to the text of the reviews, we used a -3 to +3 scoring system where papers that are seen as borderline will be scored as 0. Reviewers scored papers using half-point increments.
165
166 ```{r, echo=FALSE}
167 ## generate the score graphs
168 ggplot(data=scores) + aes(x=sub.id) + 
169   geom_hline(yintercept = 0, color="orange") +
170   geom_line(data=scores.after, aes(y=score), color="grey") + 
171   geom_point(aes(y=avg.score.after, color=decision)) + 
172   scale_x_discrete("", limits=levels(scores$sub.id), labels=c()) +
173   scale_y_continuous("Reviewer Score") +
174   scale_color_discrete("Final Decision") +
175   theme_minimal() +
176   theme(legend.position="bottom", legend.direction="horizontal")
177 ```
178
179
180 The figure above shows scores for each paper submitted. The vertical grey lines reflect the distribution of scores where the minimum and maximum scores for each paper are the ends of the lines. The colored dots show the arithmetic mean for each score (unweighted by reviewer confidence). Colors show whether the papers were accepted, rejected, or presented as a poster. It's important to keep in mind that two papers were *submitted* as posters. Although Associate Chairs made the final decisions on a case-by-case basis, most papers that had an average score of less than 0 (the horizontal orange line) were rejected and most papers with positive average scores were accepted. We ultimately accepted `r num.papers.accepted` papers (`r paste(round(num.papers.accepted / (nrow(submissions) - 2)*100), "%", sep="")`) of those submitted.
181
182 # Rebuttals
183
184 This was the first time that OpenSym used a rebuttal or author response and we are thrilled with how it went. Although they were entire optional, almost everybody used it! Authors of `r length(reviews[reviews$label == "Author response","sub.id"])` of our `r nrow(submissions)` submissions (`r round(length(reviews[reviews$label == "Author response","sub.id"]) / nrow(submissions)*100)`%!) submitted rebuttals.
185
186 ```{r, echo=FALSE}
187 # histogram of changes
188 # qplot(grid.tmp[grid.tmp$variable == "delta", "value"])
189
190 rebut.tbl <- table(scores[scores$sub.id %in% reviews[reviews$label == "Author response","sub.id"], "change"])
191
192 kable(data.frame("Lower"=rebut.tbl["decrease"],
193                  "Unchanged"=rebut.tbl["none"],
194                  "Higher"=rebut.tbl["increase"]),
195       row.names = FALSE)
196   
197 ```
198
199 The table above shows how average scores changed after authors submitted rebuttals. The table shows that rebuttals' effect was typically neutral or positive. Most average scores stayed the same but nearly two times as many increased as decreased in the post-rebuttal period. We hope that this made the process feel more fair for authors and I feel, having read them all, that it led to improvements in the quality of final papers.
200
201 # Page Lengths
202
203 In previous years, OpenSym followed most other venues in computer science by allowing submission of two kinds of papers: full papers which could be up to 10 pages long and short papers which could be up to 4. Following some other conferences, we eliminated page limits altogether. This is the text we used in [the OpenSym 2017 CFP](https://perma.cc/87QY-27FS):
204
205 > There is no minimum or maximum length for submitted papers. Rather, reviewers will be instructed to weigh the contribution of a paper relative to its length. Papers should report research thoroughly but succinctly: brevity is a virtue. A typical length of a “long research paper” is 10 pages (formerly the maximum length limit and the limit on OpenSym tracks), but may be shorter if the contribution can be described and supported in fewer pages— shorter, more focused papers (called “short research papers” previously) are encouraged and will be reviewed like any other paper. While we will review papers longer than 10 pages, the contribution must warrant the extra length. Reviewers will be instructed to reject papers whose length is incommensurate with the size of their contribution.
206
207 The following graph shows the distribution of page lengths in our final program.
208
209 ```{r, echo=FALSE}
210 pdf.pages <- read.table("opensym2017-pdf_page_lengths.list")
211 colnames(pdf.pages) <- "pages"
212
213 ggplot(data=pdf.pages) + aes(x=pages) + geom_bar() + scale_x_continuous("Pages", breaks=seq(1, 14), labels=seq(1, 14)) + scale_y_continuous("Number of papers") + coord_flip() + theme_minimal()
214 ```
215
216 In the end `r table(pdf.pages$pages > 10)["TRUE"]` of `r num.papers.accepted` published papers (`r round(table(pdf.pages$pages > 10)["TRUE"] / num.papers.accepted * 100, 2)`%) were over 10 pages. More surprisingly, `r table(pdf.pages$pages < 10)["TRUE"]` of the accepted papers (`r round(table(pdf.pages$pages < 10)["TRUE"] / num.papers.accepted * 100, 2)`%) were below the old 10-page limit. Fears that some have expressed that page limits are the only thing keeping OpenSym authors from submitting enormous rambling manuscripts seems to be unwarranted—at least so far.
217
218 # Bidding
219
220 Although, I won't post any analysis or graphs, bidding worked well. With only two exceptions, every single assigned review was to someone who had bid "yes" or "maybe" for the paper in question and the vast majority went to people that had bid "yes". However, this comes with one major proviso: people that did not bid at all were marked as "maybe" for every single paper.
221
222 Given a reviewer pool whose diversity of expertise matches that in your pool of authors, bidding works fantastically. *But everybody needs to bid*. The only problems with reviewers we had were with people that had failed to bid. 
223 It might be reviewers who don't bid are less committed to the conference, more overextended, more likely to drop things in general, etc. It might also be that reviewers who fail to bid get good matches become less interested, willing, or able to do their reviews well and on time.
224
225 Having used bidding twice as chair or track-chair, my sense is that bidding is a fantastic thing to incorporate into any conference review process. The major limitations are that you need to build a PC before the conference (rather than finding the perfect reviewers for specific papers) and you have to find ways to incentivize or communicate the importance of getting your PC members to bid.
226
227 # Conclusions
228
229 The final results were [a fantastic collection of published papers](https://blog.communitydata.cc/opensym-2017-program/). Of course, it couldn't have been possible without the huge collection of [conference chairs, associate chairs, program committee members, external reviewers, and staff supporters](http://opensym.lero.ie/organisation/organization/).
230
231 Although we tried quite a lot of new things, my sense is that nothing we tried made things worse and many things made things smoother or better. Although I'm not directly involved in organizing OpenSym 2018, I am on the OpenSym steering committee.  My sense is that most of the changes we made are going to be carried over this year.
232
233 Finally, it's also been announced that [OpenSym 2018 will be in Paris on August 22-24](http://www.opensym.org/os2018/). The call for papers should be out soon with, I suspect, a spring paper submission deadline. You should consider submitting! I hope to see you in Paris!
234
235 # This Analysis
236
237 OpenSym used the gratis version of [EasyChair](https://www.easychair.org/) to manage the conference which doesn't allow chairs to export data. As a result, data used in this this postmortem was scraped from EasyChair using two Python scripts. Numbers and graphs were created using a [knitr](https://yihui.name/knitr/) file that combines R visualization and analysis code and markdown. I've made all the code I used to produce this analysis available in [this git repository](https://code.communitydata.cc/opensym2017_postmortem.git). I hope someone else finds it useful. Because the data contains sensitive information on the review process, I'm not going to publish the data.
238

Community Data Science Collective || Want to submit a patch?