【问题标题】:Conditional Summing with multiple columns in RR中多列的条件求和
【发布时间】:2017-04-07 18:09:40
【问题描述】:

我想为每个用户绘制点与时间的关系,但我不确定如何处理这些列以实现该结果。这是我的数据的样子:

> head(data, n=3)
points   user       time
25        1      02/22/2017
0         2      02/26/2017
15        3      02/27/2017

> dput(data)
structure(list(points = c(25, 0, 15), user = c(1, 2, 3), time = c("02/22/2017", "02/26/2017", "02/27/2017")), .Names = c("points", "user", "time"), row.names = c(NA, -3L), class = "data.frame")

仅供参考,有多个用户 ID(我认为最多 15 个)。但是我想做的是对每个用户的总积分求和(然后用户列中的数字对应于用户的 ID 号。然后随着时间的推移绘制这些值(具体按天)。

这是我用来生成每位用户总积分的代码

library(data.table)
ppu = setkey(setDT(df), user_id)[, list(points=sum(points)), by=list(user_id)]

结果如下:

但我想找出每位用户每天的总积分!非常感谢任何指导。

【问题讨论】:

  • 如果您打算让任何人实际使用您的数据,请发布实际数据,而不是数据图片。 (与截屏、保存、上传、发布相比,复制/粘贴 R 控制台文本应该花费更少的精力。)
  • 诀窍是在每行添加 4 个空格。尝试突出显示控制台文本,然后运行它(假设 win,类似的技术适用于 mac/linux):writeLines(gsub("^", " ", readLines("clipboard")), "clipboard")(第二个字符串应该是四个空格)然后粘贴到您的问题中。这会强制 StackOverflow 对输出进行代码格式化(“逐字”)。
  • 不过,我将支持@student 的评论:如果您使用dput(data)(或dput(head(data)),如果很大),我们更容易消费,因为我们可以从字面上复制/粘贴并获取数据。否则,我们需要一点read.table 魔法,并不总是“足够简单”。
  • 另一边评论:我建议反对将变量命名为data。如果你在没有创建变量的情况下运行脚本,而不是有用的错误消息 (Error: object 'x' not found),你会得到一些更模糊的东西 (Error in data$x : object of type 'closure' is not subsettable,这实际上意味着我试图将 function named data() 子集化) .
  • @r2evans 突出显示 SO 文本输入框中的文本,然后键入 Ctrl-K。

标签: r time data.table


【解决方案1】:

请尝试(使用 Q 中 dput() 的结果给出的 df):

library(data.table)   # version 1.10.4 used
ppu <- setDT(df)[, .(points = sum(points)), by = .(user, time)]

ppu
#   user       time points
#1:    1 02/22/2017     25
#2:    2 02/26/2017      0
#3:    3 02/27/2017     15

这将按照df 中出现的顺序返回usertime。如果您想对结果进行排序,您有两种选择:

例如,用于打印,使用

ppu[order(user, time)]
# or
ppu[order(time, user)]

或者,如果应该键入结果,请尝试keyby

ppu <- setDT(df)[, .(points = sum(points)), keyby = .(user, time)]

一些备注:

  • 您的代码 sn-p 使用 user_id,而您的数据样本使用 user。此外,数据样本还包含一个名为 time 的列,其中包含作为字符串的日期,但在文本中您使用的是术语“day”。
  • by 接受多个分组变量。您甚至可以动态创建表达式
  • 为了简化,time 不需要强制转换为 Data 类,只要相同的日期以相同的方式写入即可。
  • data.table 语法中,.()list() 的缩写。
  • data.table 的最新版本取消了设置键的要求。

this comment,OP 询问如何

绘制每个用户的点数与时间(每天)的关系。

这需要对ppu 进行一些修改才能更好地与ggplot2 配合使用。

# coerce user to factor to get a discrete colour scale
# only required here because user was given as numeric 
ppu[, user := factor(user)]
# coerce time from character to Date class
# to get a nicely scaled x-axis instead of discrete values
ppu[, time := lubridate::mdy(time)]

现在,pointstime 分别绘制,但每个 user 都有单独的颜色编码线:

library(ggplot2)
ggplot(ppu, aes(time, points, group = user, colour = user)) + 
  geom_point() + geom_line()

好吧,如果有足够的样本数据,您可能会在此处看到线条...

【讨论】:

  • 非常感谢 - 效果很好。因此,我会做什么而不是设置键?另外,如果我想绘制每个用户的点数与时间(每天)的关系,我该怎么做呢?我认为我会绘制 ppu 与时间的关系,但 ppu 的长度会与时间不同。
  • @Chris95 我已经更新了我的答案以包括绘图内容。希望我达到了你的期望。关于为小型 data.tables 设置键,您可能根本不需要担心设置键,这要归功于自动创建的二级索引。
【解决方案2】:

首先你需要将你的日期转换成一个好的格式,为此我建议你像这样使用library(lubridate)

data$day <- mdy(data$day)

然后将每个用户每天的积分数相加:

library(plyr)
pts_user_day <- ddply(data, .(user, day), summarise, pts_day = sum(points))

随着时间的推移最终绘制所有这些:

library(ggplot2)
ggplot(pts_user_day, aes(x=day, y=pts_day, col=factor(user))) + geom_line() + scale_x_date()

希望有帮助!

【讨论】:

  • 问题标记为data.table,包含的代码sn-p包含library(data.table)。因此,使用 plyr 的答案可能不是 OP 所期望的(即使您的建议可能会导致相同的结果)。
猜你喜欢
  • 2022-01-08
  • 2022-10-06
  • 2018-04-10
  • 2014-04-13
  • 2022-11-29
  • 1970-01-01
  • 2016-11-19
  • 2019-12-11
  • 1970-01-01
相关资源
最近更新 更多