对变量 R 计数变量
Count variable on a Variable R
Tid <- c(1,1,2,2,2,3,4,4)
Uid <- c(10,10,11,11,12,13,10,14)
Data <- data.frame(Tid,Uid)
我想知道每个Tid上出现了多少个不同的Uid。
我的结果应该是这样的。
Tid, freqUid
1, 1
2, 2
3, 1
4, 2
我尝试对它使用计数,但在不止一个变量上使用它时遇到了一些问题。
我们可以使用 dplyr
中的 n_distinct
。我们按 'Tid' 分组,并在 summarise
.
内得到 'Uid' 的 n_distinct
library(dplyr)
Data %>%
group_by(Tid) %>%
summarise(freqUid=n_distinct(Uid))
# Tid freqUid
# (dbl) (int)
#1 1 1
#2 2 2
#3 3 1
#4 4 2
或者我们可以使用 data.table
中的 uniqueN
。我们将 'data.frame' 转换为 'data.table' (setDT(Data)
),按 'Tid' 分组,我们得到 'Uid'.
的 uniqueN
library(data.table)#v1.9.5+
setDT(Data)[, list(freqUid=uniqueN(Uid)), by = Tid]
# Tid freqUid
#1: 1 1
#2: 2 2
#3: 3 1
#4: 4 2
基准
这里有一些使用大数据集的基准测试
set.seed(24)
Data <- data.frame(Tid=rep(1:1e4, each=100),
Uid= sample(10:70, 1e4*100, replace=TRUE))
f1 <- function() as.data.frame.table(with(Data,
tapply(Uid, Tid, function(.) length(unique(.)))))
f2 <- function() as.data.frame(table(unique(Data)$Tid))
f3 <- function() aggregate(Uid ~ Tid, unique(Data), length)
f4 <- function() Data %>%
group_by(Tid) %>%
summarise(freqUid=n_distinct(Uid))
f5 <- function() as.data.table(Data)[, list(freqUid=uniqueN(Uid)), by = Tid]
library(microbenchmark)
microbenchmark(f1(), f2(), f3(), f4(), f5(), times=20L, unit='relative')
#Unit: relative
# expr min lq mean median uq max neval cld
#f1() 2.357808 2.506813 2.347543 2.401787 2.138740 2.706053 20 a
#f2() 10.581284 11.798583 11.456316 11.975014 11.411718 10.664648 20 b
#f3() 28.243538 27.740333 25.630334 25.042240 25.590332 23.426749 20 c
#f4() 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 20 a
#f5() 1.385114 1.369170 1.396271 1.405275 1.354914 1.473114 20 a
如果我们删除f1
和f2
中的as.data.frame
(输出格式会不同),然后运行再次进行基准测试。
f1 <- function() with(Data, tapply(Uid, Tid, function(.) length(unique(.))))
f2 <- function() table(unique(Data)$Tid)
正如@DavidArenburg 提到的,uniqueN
比 length(unique(.))
慢。因此,将其替换为 f5
f5 <- function() as.data.table(Data)[, list(freqUid=length(unique(Uid))),
by = Tid]
microbenchmark(f1(), f2(), f3(), f4(), f5(), times=20L, unit='relative')
#Unit: relative
#expr min lq mean median uq max neval cld
#f1() 3.466328 3.052508 2.789366 2.968971 3.069631 1.7850643 20 b
#f2() 11.539920 13.372543 12.067983 13.266105 13.014644 7.6774925 20 c
#f3() 33.491446 30.839725 27.339148 30.888726 29.953344 17.3956850 20 d
#f4() 1.254533 1.177933 1.083263 1.213019 1.162862 0.6981573 20 a
#f5() 1.000000 1.000000 1.000000 1.000000 1.000000 1.0000000 20 a
带基数 R
as.data.frame(table(unique(Data)$Tid))
# Var1 Freq
# 1 1 1
# 2 2 2
# 3 3 1
# 4 4 2
或者(尽管列名称的信息量较少)
aggregate(Uid ~ Tid, unique(Data), length)
# Tid Uid
# 1 1 1
# 2 2 2
# 3 3 1
# 4 4 2
这里的基本思想是只对Tid/Uid
的唯一组合进行操作,然后计算不同的Tid
个实例
编辑:
根据@nicolas 评论,我们也可以在此处添加 tapply
作为可能的解决方案
as.data.frame.table(tapply(Data$Uid, Data$Tid, function(x) length(unique(x))))
# Var1 Freq
# 1 1 1
# 2 2 2
# 3 3 1
# 4 4 2
只是为了引入另一种 dplyr 风格的方法:
library(dplyr)
distinct(Data) %>% count(Tid)
#Source: local data frame [4 x 2]
#
# Tid n
#1 1 1
#2 2 2
#3 3 1
#4 4 2
(不建议这比其他 dplyr/data.table 解决方案更快。)
关于@David 的评论,所有提出的解决方案得到的结果基本相同。但当然,我的建议是不等同于table(unique(Data)$Tid)
。它更快并且 returns 是 data.frame(不是 table
对象)。
另一种可能性:
library(functional)
by(Uid, Tid, FUN=Compose(unique, length))
或基础 R
作为@David Arenburg 下划线:
by(Uid, Tid, FUN=function(x) length(unique(x)))
Tid <- c(1,1,2,2,2,3,4,4)
Uid <- c(10,10,11,11,12,13,10,14)
Data <- data.frame(Tid,Uid)
我想知道每个Tid上出现了多少个不同的Uid。 我的结果应该是这样的。
Tid, freqUid
1, 1
2, 2
3, 1
4, 2
我尝试对它使用计数,但在不止一个变量上使用它时遇到了一些问题。
我们可以使用 dplyr
中的 n_distinct
。我们按 'Tid' 分组,并在 summarise
.
n_distinct
library(dplyr)
Data %>%
group_by(Tid) %>%
summarise(freqUid=n_distinct(Uid))
# Tid freqUid
# (dbl) (int)
#1 1 1
#2 2 2
#3 3 1
#4 4 2
或者我们可以使用 data.table
中的 uniqueN
。我们将 'data.frame' 转换为 'data.table' (setDT(Data)
),按 'Tid' 分组,我们得到 'Uid'.
uniqueN
library(data.table)#v1.9.5+
setDT(Data)[, list(freqUid=uniqueN(Uid)), by = Tid]
# Tid freqUid
#1: 1 1
#2: 2 2
#3: 3 1
#4: 4 2
基准
这里有一些使用大数据集的基准测试
set.seed(24)
Data <- data.frame(Tid=rep(1:1e4, each=100),
Uid= sample(10:70, 1e4*100, replace=TRUE))
f1 <- function() as.data.frame.table(with(Data,
tapply(Uid, Tid, function(.) length(unique(.)))))
f2 <- function() as.data.frame(table(unique(Data)$Tid))
f3 <- function() aggregate(Uid ~ Tid, unique(Data), length)
f4 <- function() Data %>%
group_by(Tid) %>%
summarise(freqUid=n_distinct(Uid))
f5 <- function() as.data.table(Data)[, list(freqUid=uniqueN(Uid)), by = Tid]
library(microbenchmark)
microbenchmark(f1(), f2(), f3(), f4(), f5(), times=20L, unit='relative')
#Unit: relative
# expr min lq mean median uq max neval cld
#f1() 2.357808 2.506813 2.347543 2.401787 2.138740 2.706053 20 a
#f2() 10.581284 11.798583 11.456316 11.975014 11.411718 10.664648 20 b
#f3() 28.243538 27.740333 25.630334 25.042240 25.590332 23.426749 20 c
#f4() 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 20 a
#f5() 1.385114 1.369170 1.396271 1.405275 1.354914 1.473114 20 a
如果我们删除f1
和f2
中的as.data.frame
(输出格式会不同),然后运行再次进行基准测试。
f1 <- function() with(Data, tapply(Uid, Tid, function(.) length(unique(.))))
f2 <- function() table(unique(Data)$Tid)
正如@DavidArenburg 提到的,uniqueN
比 length(unique(.))
慢。因此,将其替换为 f5
f5 <- function() as.data.table(Data)[, list(freqUid=length(unique(Uid))),
by = Tid]
microbenchmark(f1(), f2(), f3(), f4(), f5(), times=20L, unit='relative')
#Unit: relative
#expr min lq mean median uq max neval cld
#f1() 3.466328 3.052508 2.789366 2.968971 3.069631 1.7850643 20 b
#f2() 11.539920 13.372543 12.067983 13.266105 13.014644 7.6774925 20 c
#f3() 33.491446 30.839725 27.339148 30.888726 29.953344 17.3956850 20 d
#f4() 1.254533 1.177933 1.083263 1.213019 1.162862 0.6981573 20 a
#f5() 1.000000 1.000000 1.000000 1.000000 1.000000 1.0000000 20 a
带基数 R
as.data.frame(table(unique(Data)$Tid))
# Var1 Freq
# 1 1 1
# 2 2 2
# 3 3 1
# 4 4 2
或者(尽管列名称的信息量较少)
aggregate(Uid ~ Tid, unique(Data), length)
# Tid Uid
# 1 1 1
# 2 2 2
# 3 3 1
# 4 4 2
这里的基本思想是只对Tid/Uid
的唯一组合进行操作,然后计算不同的Tid
个实例
编辑:
根据@nicolas 评论,我们也可以在此处添加 tapply
作为可能的解决方案
as.data.frame.table(tapply(Data$Uid, Data$Tid, function(x) length(unique(x))))
# Var1 Freq
# 1 1 1
# 2 2 2
# 3 3 1
# 4 4 2
只是为了引入另一种 dplyr 风格的方法:
library(dplyr)
distinct(Data) %>% count(Tid)
#Source: local data frame [4 x 2]
#
# Tid n
#1 1 1
#2 2 2
#3 3 1
#4 4 2
(不建议这比其他 dplyr/data.table 解决方案更快。)
关于@David 的评论,所有提出的解决方案得到的结果基本相同。但当然,我的建议是不等同于table(unique(Data)$Tid)
。它更快并且 returns 是 data.frame(不是 table
对象)。
另一种可能性:
library(functional)
by(Uid, Tid, FUN=Compose(unique, length))
或基础 R
作为@David Arenburg 下划线:
by(Uid, Tid, FUN=function(x) length(unique(x)))