我正在用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()函数有关,但我现在还没想出来。
答案 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
汇总到列表列而不是将它们合并。