计算与当前行值

时间:2018-04-12 05:52:23

标签: r dplyr

假设我有一个数据框:

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.

5 个答案:

答案 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