给定一个表示这样的消息的数据框:
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
如果某些用户拥有大量消息而其他用户很少(例如帕累托分发),您将如何绘制每位用户每日平均消息数量。
感谢。
答案 0 :(得分: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)
答案 1 :(得分:1)
#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和我都必须重新创建我们自己的数据集。
答案 2 :(得分: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