9

I analyzed posting data from several SE communities and found that time gaps of almost precisely 30, 60, 90, and 120 minutes between consecutive answers are particular frequent. The figures show this pattern at 30 minutes between consecutive answers (the vertical axis is not of importance):

Clustering of answers 30 minutes after previous answer

Clustering of answers 30 minutes after previous answer (larger time spectrum

enter image description here

The pattern vanishes over time (i.e., it is strongest at 30 minutes, less stronger at 60 minutes, and so on).

I would like to understand why this pattern emerges. Please note that the gaps are not exactly 30, 60, 90, 120 minutes, so it seems to be driven by a behavioral (human-based) cause. Maybe it results from a posting strategy. I have no idea. Perhaps the experienced contributors know. Thanks!

Details on the data: Data source is the User Experience community's Posts table which I loaded into R. (1) I ordered CreationDate of the answers (answers where identified through PostTypeId==2) for each question. (2) Then, I calculated the difference between their CreationDate: timeDiff.prev.a <- difftime(as.POSIXlt(df$a.CreationDate,tz="UTC"),as.POSIXlt(c(NA,df$a.CreationDate[1:length(df$a.CreationDate)-1]),tz="UTC")))

The figure is created using the variable timeDiff.prev.a as horizontal: qplot(y=noise,x=timeDiff.prev.a,data=data.ux.01,ylab="noise",xlab="time since preceding answer (in mins)",ylim=c(0,1),xlim=c(25,35))

I also checked the Software Engineering community using the same procedure and finding the same pattern.

Here is the R code which assembled for this post (it's a bit quick and dirty, because I found the pattern accidentally and the original code is much longer):

library(plyr)
library(dplyr)
library(ggplot2)

## Read data (which is spread over 3 csv files):
data.ux.posts_a <- read.csv(file="\\data\\20190603_User Experience\\Posts_a.csv",stringsAsFactors=F)
data.ux.posts_b <- read.csv(file="\\data\\20190603_User Experience\\Posts_b.csv",stringsAsFactors=F)
data.ux.posts_c <- read.csv(file="\\data\\20190603_User Experience\\Posts_c.csv",stringsAsFactors=F)
data.ux.posts.00 <- rbind(data.ux.posts_a,data.ux.posts_b,data.ux.posts_c)

## Remove the most recent questions:
data.ux.posts.00 <- subset(data.ux.posts.00,!(PostTypeId==1&CreationDate>="2019-04-02 02:05:36"))

## Split into questions and answers:
data.ux.a.00 <- subset(data.ux.posts.00,PostTypeId==2)
data.ux.q.00 <- subset(data.ux.posts.00,PostTypeId==1)
colnames(data.ux.a.00) <- paste("a.",colnames(data.ux.a.00),sep="")
colnames(data.ux.q.00) <- paste("q.",colnames(data.ux.q.00),sep="")

### Merge so that answers are nested in their questions:
data.ux.00 <- merge(x=data.ux.q.00,y=data.ux.a.00,by.x="q.Id",by.y="a.ParentId",all.y=F)

### Calculate the time differences
data.ux.00 <- data.ux.00[order(data.ux.00$q.Id,data.ux.00$a.CreationDate),]

result.block2 <- ddply(data.ux.00,.(q.Id),
                       function(df) data.frame(
                         timeDiff.prev.a = difftime(as.POSIXlt(df$a.CreationDate,tz="UTC"),as.POSIXlt(c(NA,df$a.CreationDate[1:length(df$a.CreationDate)-1]),tz="UTC"))
                       ))
data.ux.01 <- cbind(data.ux.00,result.block2)

noise <- runif(n=length(subset(data.ux.01)$timeDiff.prev.a), min=0,max=1)

qplot(y=noise,x=timeDiff.prev.a,data=subset(data.ux.01),ylab="noise",xlab="time since preceding answer (in mins)",ylim=c(0,1),xlim=c(25,35))
  • 4
    Can you show how you gathered that data and transformed it into the diagram exactly please? – πάντα ῥεῖ Jul 25 at 18:10
  • @πάνταῥεῖ, thanks! I edited the question. I can clean my code and post all of it if that helps?? – Michael227 Jul 25 at 18:29
  • Might be a caching issue, about how often that data is updated. – πάντα ῥεῖ Jul 25 at 18:34
  • 1
    > "Might be a caching issue, about how often that data is updated. – πάντα ῥεῖ 1 min ago" But then we would expect precise gaps, wouldn't we? This is not the case. – Michael227 Jul 25 at 18:36
  • 4
    Maybe it is related to when the batch job runs to update rss feeds and send notifications to tagfollowers? – rene Jul 25 at 18:41
  • 1
    I don't believe that plot -- especially since there should be a strong cluster of answers with only a few minutes (or seconds) separation and the plot cuts off at 25 minutes. The time from question to first answer should also be included. – Awesome Poodles Jul 25 at 18:43
  • @rene, that might explain a consistent gap between question post (or tag edits) and answers, but not sure it would explain consecutive answer separation. – Awesome Poodles Jul 25 at 18:45
  • 3
    @Michael227 Well, you show some piece of R code how you're processing the data, can you also show how you're retrieving it please? – πάντα ῥεῖ Jul 25 at 18:47
  • @AwesomePoodles: I added a plot with the full (left-hand) spectrum. Please note that this is independent of the time of the question. – Michael227 Jul 25 at 18:47
  • @AwesomePoodles something seems strange: data.stackexchange.com/stackoverflow/query/1080662#graph you would expect a kind of a flatliner, no? – rene Jul 25 at 18:50
  • 3
    @rene, don't ignore the zoom effect on the vertical scale. You show a 2.2% variation in that plot. That's pretty flat for real-life data. See also: xkcd.com/2023 – Awesome Poodles Jul 25 at 18:57
  • @rene questions are affected as well, and it's only Stack Overflow; other sites show a more random graph. – Glorfindel Jul 25 at 19:09
  • @Glorfindel, your plot is really pretty flat (as expected). – Awesome Poodles Jul 25 at 19:18
  • @πάνταῥεῖ, I assembled the R code and tested it.I have the data on this dropbox link (the path must be adapted): dropbox.com/sh/lup2w7ne2aqlmgi/AACXvIjr31WES7-sjcliWxtka?dl=0 – Michael227 Jul 25 at 19:24
9

You can get the time separation between a question and the first answer, and then between each successive answer with a SEDE query like:

WITH timeSeparation AS (
    SELECT
                q.Id                AS qstId
                , c.*
    FROM        Posts q
    CROSS APPLY (
        SELECT  a.Id                AS postId
                , a.CreationDate    AS postDate
                , minsAfter = DATEDIFF (mi, ISNULL (LAG (a.CreationDate) OVER (ORDER BY a.CreationDate), q.CreationDate), a.CreationDate)
        FROM    Posts a
        WHERE   a.PostTypeId    = 2
        AND     a.ParentId      = q.Id
    ) c
    WHERE       q.PostTypeId    = 1
    AND         q.AnswerCount   > 0
)
SELECT      ts.minsAfter
            , [Number of Answers with the given delay] = COUNT (ts.postId)
FROM        timeSeparation ts
WHERE       ts.minsAfter < 301  -- otherwise long tail swamps out plot
AND         ts.minsAfter >= 0   -- Answers can be older than questions if they were merged in. Discard those.
GROUP BY    ts.minsAfter
ORDER BY    ts.minsAfter


If you do that for the User Experience site, you get data like this:

Post separation for UX

If you do that for the Super User site, you get data like this:

Post separation for Superuser

(Alas, my SQL-fu is not up to the challenge of getting the query to run on Stack Overflow's data set.)

Anyway, all such plots that I've run resemble a Poisson-like distribution. There is nothing special going on at 30, 60, 90, etc. minutes.

Might the graphs in the question be an artifact of the stat tool that was used?

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .