1

给定一个表示如下消息的数据框:

df <- structure(list(message.id = c(123L, 456L), user.id = c(999L, 888L), 
      message.date = structure(c(1310950467, 1311119810), class = c("POSIXct", 
      "POSIXt"), tzone = "")), .Names = c("messageid", "user.id", 
      "message.date"), row.names = c(NA, -2L), class = "data.frame")

head(df)
message.id   user.id    message.date         
123         999       2011-07-17 17:54:27
456         888       2011-07-19 16:56:50

假设某些用户有很多消息而其他用户很少(例如帕累托分布),您将如何绘制每个用户的每日平均消息数。

谢谢。

4

3 回答 3

3

您的示例非常小,无法真正使用,因此我模拟了一个应该相同的更大数据框:

set.seed(1)
start <- strptime("2012-01-01 00:00:00",format="%Y-%m-%d %H:%M:%S")
end <- strptime("2012-03-01 00:00:00",format="%Y-%m-%d %H:%M:%S")

df <- data.frame(
  message.id = 1:1000,
  user.id = sample(1:10,1000,TRUE,prob=1:10),
  message.date = seq(start,end,length=1000))

然后首先我们需要将日期提取为日期(而不是 POSIXt):

df$date <- as.Date(df$message.date)

然后我认为我们可以plyr用来计算每个用户每天的平均消息数,如下所示:

library("plyr")
df2 <- ddply(df,.(user.id),summarize,AvPerDay = mean(sapply(seq(min(df$date),max(df$date),by="day"),function(x)sum(date==x))))

新的数据框df2给了我:

   user.id  AvPerDay
1        1 0.3278689
2        2 0.6229508
3        3 0.9836066
4        4 1.1311475
5        5 1.3442623
6        6 1.8524590
7        7 1.8032787
8        8 2.8032787
9        9 2.5081967
10      10 3.0163934

要绘制它,您可以制作一个条形图:

barplot(df2$user.id,df2$AvPerDay)
于 2012-04-22T16:37:46.120 回答
1

Sacha的更好,但当我看到他的回答时,我刚刚完成。这是一种可能的基本方法:

#Make my own data
set.seed(15)
df <- data.frame(messageid= sample(1:1000, 1000), user.id = 
    rep(901:925, each=40), message.date = sample(seq(Sys.time(), 
    length.out = 10000, by = "hours"), 1000, replace=T))

#Make a date column
df$date <- unlist(strsplit(as.character(df$message.date), " "))[c(T, F)]

#split on user id
pidLIST <- split(df, df[, 'user.id'])
#sum and get an average by date
df2 <- data.frame(user.id=as.factor(names(pidLIST)), 
    aveMESS = sapply(seq_along(pidLIST), 
    function(i) mean(aggregate(user.id~date, pidLIST[[i]], length)[, 2])))

plot(df2)

正如你所知道的,我不经常使用日期。

PS 当您提供一个最小的可重现示例(如果它足够大以供使用)时,它会很有帮助。Sacha 和我都必须重新创建我们自己的数据集。

于 2012-04-22T16:42:57.463 回答
0

尝试不同的方法,我尝试了这个图:每天的箱线图显示用户消息计数的分布,以及连接每个用户的平均消息数的线。这是目标情节:

每天用户消息的分布和平均值

我首先使用@Sacha Epskamp 的方法生成数据。我生成了一个大型数据集,以便为预期的情节提供一些东西

library("ggplot2")
library("lubridate")


# This code from Sacha Eskamp
# http://stackoverflow.com/a/10269840/1290420

# Generate a data set
set.seed(1)
start <- strptime("2012-01-05 00:00:00",
                  format="%Y-%m-%d %H:%M:%S")
end <- strptime("2012-03-05 00:00:00",
                format="%Y-%m-%d %H:%M:%S")

df <- data.frame(message.id = 1:10000,
                 user.id = sample(1:30,10000,
                                 TRUE,
                                 prob=1:30),
                 message.date = seq(start,
                                   end,
                                   length=10000)
                 )

然后我努力将数据框整理成适合情节的形状。我相信plyr大师将能够大大改善这一点。

# Clean up the data frame and add a column 
# with combined day-user
df$day <- yday(df$message.date)
df <- df[ df$day!=65, c(2,4) ]
df$day.user <- paste(df$day, df$user.id, sep="-")

# Copy into new data frame with counts for each
# day-user combination
df2 <- aggregate(df, 
                 by=list(df$day, 
                         df$day.user), 
                 FUN="length"
                 )
df2 <- df2[,c(1,2,3)]
names(df2) <- c("day", "user", "count")
df2$user <- gsub(".+-(.+)", "\\1", df2$user)

然后绘制情节是简单的部分:

p <- ggplot(df2,
            aes(x=day,
                y=count))
p <- p + geom_boxplot(aes(group=day), colour="grey80")
p <- p + stat_summary(fun.y=mean, 
                      colour="steelblue", 
                      geom="line",
                      size=1)
p <- p + stat_summary(fun.y=mean, 
                      colour="red", 
                      geom="point",
                      size=3)
p
于 2012-04-23T16:47:21.953 回答