4

我有一个这样的数据框:

         date      time userid        status
1  02/25/2012  09:22:10   aabc     logged_in
2  02/25/2012  09:30:10   aabc    logged_out
3  02/25/2012  09:29:20   abbc    logged_out
4  02/25/2012  09:27:30    abc     logged_in
5  02/25/2012  09:26:29    abc  login_failed
6  02/25/2012  09:26:39    abc  login_failed
7  02/25/2012  09:26:52    abc  login_failed
8  02/25/2012  09:27:09    abc  login_failed
9  02/25/2012  09:27:20    abc  login_failed
10 02/25/2012  09:24:10   abdc     logged_in
11 02/25/2012  09:24:12   abdc    logged_out
12 02/25/2012  09:22:10   abhc     logged_in
13 02/25/2012  09:30:10   abuc     logged_in
14 02/25/2012  09:30:14   abuc    logged_out
15 02/25/2012  09:29:40    baa     logged_in

我想要每个用户标识的 login_failures 的用户标识、状态和“计数”。我这样做了:

ddply(mytbl, c('userid', 'status'), function(x) c(count=nrow(x))),但这给出了所有用户标识的计数。我想将我的输出限制为仅那些状态为“login_failed”的用户标识。有任何想法吗?我见过有关按数字字段分组的问题,但没有看到有关字符串的问题。

我对 plyr 的所有功能都不是很熟悉。很高兴看到如何使用汇总、聚合、sqldf、data.table 等来完成此操作。慢慢了解它们中的每一个。

谢谢斯里

4

4 回答 4

5
require(data.table)
DT = as.data.table(mytbl)

DT[status=="login_failed", .N, by=userid]

要命名列:

DT[status=="login_failed", list(failed_logins=.N), by=userid]
于 2012-10-03T20:17:11.287 回答
2
ddply(mytbl, .(userid), transform, 
failed_logins = length(which(status=="login_failed")))

根据 Brian Diggs 的观点,我写了上面的内容,因为我假设您希望将此信息附加到原始数据集中。如果没有,并且您只需要摘要,请替换transformsummarise.

于 2012-10-03T18:10:58.047 回答
2

与@Maiasaura 略有不同的方法。我过滤到仅失败的登录,然后进行总结。区别在于那些有登录但没有失败登录的 ' 是否userid出现在最终结果中是否为 0。

ddply(mytbl[mytbl$status=="login_failed",], .(userid), 
  summarise, failed_logins=length(status))

这给

> ddply(mytbl[mytbl$status=="login_failed",], .(userid), 
+   summarise, failed_logins=length(status))
  userid failed_logins
1    abc             5

要完成这些方法,如果你想要所有userid的:

ddply(mytbl, .(userid), 
  summarise, failed_logins = sum(status=="login_failed"))

这使

> ddply(mytbl, .(userid), 
+   summarise, failed_logins = sum(status=="login_failed"))
  userid failed_logins
1   aabc             0
2   abbc             0
3    abc             5
4   abdc             0
5   abhc             0
6   abuc             0
7    baa             0
于 2012-10-03T18:16:26.403 回答
2

这是使用的基本 R 解决方案aggregate()

setNames(aggregate(status ~ userid,
                   mytbl[mytbl$status == "login_failed", ],
                   function(x) length(x)),
         c("userid", "failed_logins"))
#   userid failed_logins
# 1    abc             5

更新

想到的另一个有用的功能是ave()您可以通过以下方式使用它:

  • 首先,用于ave()在数据集中添加一个新列,该列获取每个用户的每个活动的运行计数。(注意:我必须确保“userid”和“status”列是字符类,而不是让它为我工作的因素)。

    mytbl$status_seq <- ave(mytbl$status, mytbl$userid, 
                            mytbl$status, FUN = seq_along)
    head(mytbl)
    #         date     time userid       status status_seq
    # 1 02/25/2012 09:22:10   aabc    logged_in          1
    # 2 02/25/2012 09:30:10   aabc   logged_out          1
    # 3 02/25/2012 09:29:20   abbc   logged_out          1
    # 4 02/25/2012 09:27:30    abc    logged_in          1
    # 5 02/25/2012 09:26:29    abc login_failed          1
    # 6 02/25/2012 09:26:39    abc login_failed          2
    
  • 其次,aggregate()如前所述使用,为您感兴趣的条件设置子集,并检索max值。

    aggregate(status_seq ~ userid, 
              mytbl[mytbl$status == "login_failed", ],
              function(x) max(x))
    #   userid status_seq
    # 1    abc          5
    
    aggregate(status_seq ~ userid, 
              mytbl[mytbl$status == "logged_out", ],
              function(x) max(x))
    #   userid status_seq
    # 1   aabc          1
    # 2   abbc          1
    # 3   abdc          1
    # 4   abuc          1
    

请注意,ave()如果您使用,可能会更有趣

mytbl$status_seq <- ave(mytbl$status, mytbl$date, mytbl$userid, mytbl$status, 
                        FUN = seq_along)

因为这将重置数据集中每一天的计数器。

最后(冒着分享一个可能明显的解决方案的风险),因为您只对计数感兴趣,您可能想要探索table(),它会立即为您提供所有信息:

table(mytbl$userid, mytbl$status)
# 
#      logged_in logged_out login_failed
# aabc         1          1            0
# abbc         0          1            0
# abc          1          0            5
# abdc         1          1            0
# abhc         1          0            0
# abuc         1          1            0
# baa          1          0            0
于 2012-10-03T18:25:14.513 回答