使用R进行数据重组

时间:2014-10-14 15:03:25

标签: r split-apply-combine

我有一个如下所示的数据集(dat):

 Person       IPaddress
36598035    222.999.22.99
36598035    222.999.22.99
36598035    222.999.22.99
36598035    222.999.22.99
36598035    222.999.22.99
36598035    444.666.44.66
37811171    111.88.111.88
37811171    111.88.111.88
37811171    111.88.111.88
37811171    111.88.111.88
37811171    111.88.111.88

它反映了在一段时间内登录网站的个人的实例。我需要数据看起来像这样:

Person        IPaddress      Number of Logins
36598035    222.999.22.99           6
37811171    111.88.111.88           5

因此,不是同一个人的多个条目,每个人只有一行,并计算他们登录的次数。

此外,您在我的示例中注意到,人员36598035在多于1个IP地址下登录。发生这种情况时,我希望最终数据集中的IP地址反映模式IP地址 - 换句话说,就是个人最频繁登录的IP地址。

3 个答案:

答案 0 :(得分:5)

这是一种方法。

library(dplyr)

mydf %>%
    group_by(Person, IPaddress) %>% # For each combination of person and IPaddress
    summarize(freq = n()) %>% # Get total number of log-in
    arrange(Person, desc(freq)) %>% # The most frequent IP address is in the 1st row for each user
    group_by(Person) %>% # For each user
    mutate(total = sum(freq)) %>% # Get total number of log-in
    select(-freq) %>% # Remove count
    do(head(.,1)) # Take the first row for each user

#    Person     IPaddress total
#1 36598035 222.999.22.99     6
#2 37811171 111.88.111.88     5

<强>更新

dplyr 0.3现在已经出局了。所以,你也可以做以下事情。使用count缩短一行。我还使用slice作为@aosmith推荐。

mydf %>%
    count(Person, IPaddress) %>%
    arrange(Person, desc(n)) %>%
    group_by(Person) %>%
    mutate(total = sum(n)) %>%
    select(-n) %>%
    slice(1)

答案 1 :(得分:4)

您可以使用data.table获得简明的解决方案:

library(data.table)
setDT(dat)
dat[, list(IPaddress=names(which.max(table(IPaddress))),
           Logins=.N), 
    by=Person]

答案 2 :(得分:1)

尝试:

ddf
     Person     IPaddress
1  36598035 222.999.22.99
2  36598035 222.999.22.99
3  36598035 222.999.22.99
4  36598035 222.999.22.99
5  36598035 222.999.22.99
6  36598035 444.666.44.66
7  37811171 111.88.111.88
8  37811171 111.88.111.88
9  37811171 111.88.111.88
10 37811171 111.88.111.88
11 37811171 111.88.111.88

dd1 = data.table(with(ddf, table(Person, IPaddress)))[rev(order(N))][!duplicated(Person)]
dd1
     Person     IPaddress N
1: 36598035 222.999.22.99 5
2: 37811171 111.88.111.88 5

dd1$all_login_count = data.table(with(ddf, table(Person)))$V1
dd1
     Person     IPaddress N all_login_count
1: 36598035 222.999.22.99 5               6
2: 37811171 111.88.111.88 5               5