假设我有一个数据框:
df <- data.frame(SID=sample(1:4,15,replace=T), Var1=c(rep("A",5),rep("B",5),rep("C",5)), Var2=sample(2:4,15,replace=T))
出现了这样的事情:
SID Var1 Var2
1 4 A 2
2 3 A 2
3 4 A 3
4 3 A 3
5 1 A 4
6 1 B 2
7 3 B 2
8 4 B 4
9 4 B 4
10 3 B 2
11 2 C 2
12 2 C 2
13 4 C 4
14 2 C 4
15 3 C 3
我希望完成的是找到唯一SID的计数(请参阅下面的更新,这应该有唯一(SID,Var1)组合的计数),其中给定的行&#39; s Var1从此计数中排除,计数在Var2上分组。所以对于上面的例子,我想输出:
SID Var1 Var2 Count.Excluding.Var1
1 4 A 2 3
2 3 A 2 3
3 4 A 3 1
4 3 A 3 1
5 1 A 4 3
6 1 B 2 3
7 3 B 2 3
8 4 B 4 3
9 4 B 4 3
10 3 B 2 3
11 2 C 2 4
12 2 C 2 4
13 4 C 4 2
14 2 C 4 2
15 3 C 3 2
对于第一次观察,我们的计数为3,因为对于给定的Var2值(在这种情况下为2),有3个(SID,Var1)的唯一组合,其中Var1!= A(第一次观察的Var1值) - 具体来说,计数包括观察6,7和11,但不包括12,因为我们已经考虑了(SID,Var1)=(2,C)而不是第2行,因为我们不希望Var1为&#34; A&#34 ;.所有这些行都具有相同的Var2值。
我最好使用dplyr函数和%&gt;%运算符。 &安培;
更新
我为上面的混乱和错误的解释道歉。我纠正了我打算在paranthesis中要求的内容,但我也离开了原来的措词,因为大多数答案似乎都是这样解释的。
至于这个例子,我为没有设置种子而道歉。对于第11行和第12行的Count.Excluding.Var1似乎存在一些混淆。对于唯一(SID,Var1)组合,行11和12应该有意义,因为这些计数行1,2,6和7 xor 8.
答案 0 :(得分:2)
一个简单的mapply
可以解决问题。但是,当OP请求基于%&gt;%的解决方案时,选项可以是:
df %>% mutate(Count.Excluding.Var1 =
mapply(function(x,y)nrow(unique(df[df$Var1 != x & df$Var2 == y,1:2])),.$Var1,.$Var2))
# SID Var1 Var2 Count.Excluding.Var1
# 1 4 A 2 3
# 2 2 A 3 3
# 3 4 A 4 3
# 4 4 A 4 3
# 5 3 A 4 3
# 6 4 B 3 1
# 7 3 B 3 1
# 8 3 B 3 1
# 9 4 B 2 3
# 10 2 B 3 1
# 11 2 C 2 2
# 12 4 C 4 2
# 13 1 C 4 2
# 14 1 C 2 2
# 15 3 C 4 2
数据:强>
以上结果基于OP提供的原始数据。
df <- data.frame(SID=sample(1:4,15,replace=T), Var1=c(rep("A",5),rep("B",5),rep("C",5)), Var2=sample(2:4,15,replace=T))
答案 1 :(得分:0)
无法想到dplyr
解决方案,但这里有一个apply
df$Count <- apply(df, 1, function(x) length(unique(df$SID[(df$Var1 != x['Var1']) & (df$Var2 == x['Var2'])])))
# SID Var1 Var2 Count
# 1 4 A 2 3
# 2 3 A 2 3
# 3 4 A 3 1
# 4 3 A 3 1
# 5 1 A 4 2
# 6 1 B 2 3
# 7 3 B 2 3
# 8 4 B 4 3
# 9 4 B 4 3
# 10 3 B 2 3
# 11 2 C 2 3
# 12 2 C 2 3
# 13 4 C 4 2
# 14 2 C 4 2
# 15 3 C 3 2
答案 2 :(得分:0)
根据要求,这是dplyr
解决方案。为了将来参考,请使用set.seed
,以便我们可以使用sample
重现您想要的输出,否则我必须手动输入数据...
我认为这是你的逻辑?您希望每个n_distinct(SID)
都有Var2
,但是对于每一行,您希望排除与当前行具有相同Var1
的行。因此,这里的关键观察是第3行,其中简单的分组汇总将产生2的计数。在Var2 = 3
的行中,第3行具有SID = 4
,第4行具有SID = 3
,行15有SID = 3
,但我们不计算第3行或第4行,因此最终计数是一个唯一的SID
。
我们首先得到每个SID
的唯一Var2
计数,然后是每个SID
组合的唯一Var1, Var2
计数。对于每个组合,首次计数对于附加唯一SID
的数量而言太大,因此我们将其减去并添加一个。有一个边缘情况,对于Var1
,只有一个对应Var2
。这应该返回0
,因为您排除了SID
的所有可能值。我添加了两行来说明这一点。
library(tidyverse)
df <- read_table2(
"SID Var1 Var2
4 A 2
3 A 2
4 A 3
3 A 3
1 A 4
1 B 2
3 B 2
4 B 4
4 B 4
3 B 2
2 C 2
2 C 2
4 C 4
2 C 4
3 C 3
1 D 5
2 D 5"
)
df %>%
group_by(Var2) %>%
mutate(SID_per_Var2 = n_distinct(SID)) %>%
group_by(Var1, Var2) %>%
mutate(SID_per_Var1Var2 = n_distinct(SID)) %>%
ungroup() %>%
add_count(Var1) %>%
add_count(Var1, Var2) %>%
mutate(
Count.Excluding.Var1 = if_else(
n > nn,
SID_per_Var2 - SID_per_Var1Var2 + 1,
0
)
) %>%
select(SID, Var1, Var2, Count.Excluding.Var1)
#> # A tibble: 17 x 4
#> SID Var1 Var2 Count.Excluding.Var1
#> <int> <chr> <int> <dbl>
#> 1 4 A 2 3.
#> 2 3 A 2 3.
#> 3 4 A 3 1.
#> 4 3 A 3 1.
#> 5 1 A 4 3.
#> 6 1 B 2 3.
#> 7 3 B 2 3.
#> 8 4 B 4 3.
#> 9 4 B 4 3.
#> 10 3 B 2 3.
#> 11 2 C 2 4.
#> 12 2 C 2 4.
#> 13 4 C 4 2.
#> 14 2 C 4 2.
#> 15 3 C 3 2.
#> 16 1 D 5 0.
#> 17 2 D 5 0.
由reprex package(v0.2.0)创建于2018-04-12。
答案 3 :(得分:0)
这里是使用purrr
的解决方案 - 如果您愿意,可以将其包装在mutate
语句中,但我不知道它在这种特殊情况下会增加很多。< / p>
library(purrr)
df$Count.Excluding.Var1 = map_int(1:nrow(df), function(n) {
df %>% filter(Var2 == Var2[n], Var1 != Var1[n]) %>% distinct() %>% nrow()
})
(更新了Calum You的评论输入。谢谢!)
答案 4 :(得分:0)
100%tidyverse
解决方案:
library(tidyverse) # dplyr + purrr
df %>%
group_by(Var2) %>%
mutate(count = map_int(Var1,~n_distinct(SID[.x!=Var1],Var1[.x!=Var1])))
# # A tibble: 15 x 4
# # Groups: Var2 [3]
# SID Var1 Var2 count
# <int> <chr> <int> <int>
# 1 4 A 2 3
# 2 3 A 2 3
# 3 4 A 3 1
# 4 3 A 3 1
# 5 1 A 4 3
# 6 1 B 2 3
# 7 3 B 2 3
# 8 4 B 4 3
# 9 4 B 4 3
# 10 3 B 2 3
# 11 2 C 2 4
# 12 2 C 2 4
# 13 4 C 4 2
# 14 2 C 4 2
# 15 3 C 3 2