我正在使用R分析我的Web服务器日志:
data = read.table("/path/to/log", sep=" ")
Run Code Online (Sandbox Code Playgroud)
这些日志包括最终用户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
Run Code Online (Sandbox Code Playgroud)
但我还想添加一个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
Run Code Online (Sandbox Code Playgroud)
在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;
Run Code Online (Sandbox Code Playgroud)
这可能与aggregate()函数有关,但我现在还没想出来.
akr*_*run 10
我们可以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)))
Run Code Online (Sandbox Code Playgroud)
如果我们想要一个base R解决方案
do.call(data.frame, aggregate(ip~user_id, data,
FUN= function(x) c(freq= length(unique(ip)), ips=toString(unique(ip))))
Run Code Online (Sandbox Code Playgroud)
在data.table我们能做到:
library(data.table)
setDT(data)
data[ , .N , by = user_id]
Run Code Online (Sandbox Code Playgroud)
请注意,在最新版本data.table(自提交cd756e2,2015-09-26,此处为安装说明)中,此计数操作已针对速度进行了优化(根据一些基准测试,应该大约快8倍).
对于后者,这将起作用:
data[ , paste(unique(ip), collapse = ","), by = user_id]
Run Code Online (Sandbox Code Playgroud)
要同时获得两者:
data[ , .(freq = .N, ips = paste(unique(ip), collapse = ",")),
by = user_id]
Run Code Online (Sandbox Code Playgroud)
如果你想按频率对它进行排序,找出"最大的罪魁祸首"是谁:
data[ , .(freq = .N, ips = paste(unique(ip), collapse = ",")),
by = user_id][order(-freq)]
Run Code Online (Sandbox Code Playgroud)