我有这两列的DF:P_ID和PR_ID。每个行都有重复的行,有些P_ID有多个PR_ID,反之亦然。 可重复的例子:
DF <- data.frame(
'p_id' = sample(100:300, 100, replace=T),
'pr_id' = sample(100:300, 100, replace=T)
)
我想根据每个p_id有多少pr_id来添加一个新的列pr_count到DF。
在实践中,一些p_ids没有任何pr_id。我希望他们的pr_count为0。
所需的输出格式:
p_id pr_id pr_count
---- ---- --------
1 2 0
答案 0 :(得分:1)
数字ID值
为此,ave()
是您正在寻找的主力。使用一些没有pr_id的p_id获取数据框,反之亦然:
DF <- data.frame(
'p_id' = sample(100:300, 100, replace=T),
'pr_id' = sample(100:300, 100, replace=T)
)
DF$pr_id[sample(1:100,10)] <- NA
DF$p_id[sample(1:100,10)] <- NA
使用ave()
创建向量pr_count
DF <- within(DF,{
pr_count <- ave(pr_id,p_id,
FUN = function(x)length(na.omit(x))
)
pr_count[is.na(p_id)] <- 0
})
请注意,pr_count
为p_id
时,您必须替换NA
中的值。默认情况下,ave()
只会在pr_id
为p_id
的地方复制NA
的值。
一般解决方案
您必须记住,ave()
将创建一个与初始x
参数类型相同的向量(在本例中为pr_id
)。因此,如果您有字符ID,则还需要在结尾处转换为数字:
DF <- data.frame(
'p_id' = sample(letters, 100, replace=T),
'pr_id' = sample(LETTERS, 100, replace=T),
stringsAsFactors = FALSE
)
DF$pr_id[sample(1:100,10)] <- NA
DF$p_id[sample(1:100,10)] <- NA
DF <- within(DF,{
pr_count <- ave(pr_id,p_id,
FUN = function(x)length(na.omit(x))
)
pr_count[is.na(p_id)] <- 0
pr_count <- as.numeric(pr_count)
})
这再次给出了期望的结果:
> str(DF)
'data.frame': 100 obs. of 3 variables:
$ p_id : chr "m" "f" "u" "n" ...
$ pr_id : chr "Y" "W" "R" "M" ...
$ pr_count: num 2 2 3 2 2 2 2 5 4 2 ...
警告 ave()
的这种行为也意味着您会遇到很多因素问题。在使用此功能之前,请确保您的ID不会作为数据框中的因素存储!!!
答案 1 :(得分:0)
尝试:
'p_id' = sample(100:300, 10, replace=T)
'pr_id' = sample(100:300, 10, replace=T)
DF <- data.frame(p_id, pr_id)
outdf = expand.grid(p_id, pr_id)
outdf$count = ifelse(outdf$Var1==p_id & outdf$Var2==pr_id, 1, 0)
names(outdf)= c("p_id","pr_id","count")
head(outdf)
p_id pr_id count
1 295 193 1
2 112 193 0
3 283 193 0
4 163 193 0
5 202 193 0
6 135 193 0