使用R到COUNT()和GROUP_CONCAT(DISTINCT x)

时间:2015-12-14 13:26:15

标签: r

我正在用R:

分析我的网络服务器日志
data = read.table("/path/to/log", sep=" ")

这些日志包括最终用户的IP地址和USER_ID(登录后)。

我正在寻找比平常更活跃的用户,或使用比平常更多的IP地址。

我目前可以通过USER_ID来对R进行分组并计算记录:

counts <- ddply(data, .(data$user_id), nrow);
names(counts) <- c("user_id", "freq");
print(counts[order(counts$freq),c(2,1)], row.names = FALSE);

freq  user_id
   1    10171
  40     7433
  94      210
 102     2043

但我还想添加一个GROUP_CONCAT(DISTINCT IP)的等价物,如SQL中所示,我也可以看到该用户的不同IP地址列表。

freq  user_id  ips
   1    10171  192.168.0.1
  40     7433  192.168.0.5,192.168.0.2
  94      210  192.168.0.9
 102     2043  192.168.0.1,192.168.0.3,192.168.0.8

在SQL中,它看起来像:

SELECT
    user_id,
    COUNT(id) AS freq,
    GROUP_CONCAT(DISTINCT ip SEPARATOR ",") AS ips
FROM
    log_table
GROUP BY
    user_id
ORDER BY
    freq ASC;

这可能与aggregate()函数有关,但我现在还没想出来。

2 个答案:

答案 0 :(得分:9)

我们可以dplyr。我们按'user_id'进行分组,然后将'freq'作为行数(n())和'ips'作为paste(unique(ip), collapse=', ')(或者我们使用toString作为包装器)。

library(dplyr) 
data %>%
    group_by(user_id) %>%
    summarise(freq= n(), ips= toString(unique(ip)))
    #not sure we wanted the nrow or `length`  of `unique` 'ip'
    #if the latter is the case
    #summarise(freq=n_distinct(ip), ips = toString(unique(ip)))

如果我们想要base R解决方案

do.call(data.frame, aggregate(ip~user_id, data,
    FUN= function(x) c(freq= length(unique(ip)), ips=toString(unique(ip)))) 

答案 1 :(得分:6)

data.table我们可以做到:

library(data.table)
setDT(data)
data[ , .N , by = user_id]

请注意,在data.table中,此计数操作已针对速度进行了优化,因为它非常常见(see benchmarks,请记得检查verbose输出以获取有用的诊断信息。

对于后者,这将起作用:

data[ , paste(unique(ip), collapse = ","), by = user_id]

同时获得两者:

data[ , .(freq = .N, ips = paste(unique(ip), collapse = ",")),
     by = user_id]

如果您想按频率对其进行排序,以找出“最大的罪魁祸首”:

data[ , .(freq = .N, ips = paste(unique(ip), collapse = ",")),
     by = user_id][order(-freq)]

根据您的使用情况,您可能还会考虑将ip汇总到列表列而不是将它们合并。