根据情况引用dplyr组中的特定值

时间:2018-10-21 00:42:46

标签: r dplyr

我有类似下面的数据,表示实体之间的交互。

> library(tidyverse)
> set.seed(20)
> dta <- data_frame(group=c(1,1,2,2,2,3,3,3),
           flag=c(1,0,1,0,0,0,1,1),
           name=c('a','b','a','c','d','b','c','c'),
           amount=rnorm(8,20))
# A tibble: 8 x 4
  group  flag name  amount
  <dbl> <dbl> <chr>  <dbl>
1     1     1  a      21.2
2     1     0  b      19.4
3     2     1  a      21.8
4     2     1  c      18.7
5     2     0  d      19.6
6     3     0  b      20.6
7     3     1  c      17.1
8     3     1  c      19.1

可能存在一对一关系,一个实体发送给许多其他实体,或者许多实体从一个实体接收。 “组”列表示交互,而标志表示发送/接收(与发生的情况无关)。

对于网络分析,我需要group_by组列,然后创建一个名为“ to”的列,该列包含组中行的“名称”值,其中标志是唯一的1或在其组中为0。在一对一交互的情况下,我用flag == 1从行中分配名称。

我想要这样的东西:

dta %>%
  group_by(group) %>%
  mutate(to = case_when(sum(.$flag) == 1 ~ .$name[.$flag == 1],
                        sum(.$flag == 0) == 1 ~ .$name[.$flag == 0],
                        TRUE ~ .$name[.$flag == 1]))

  group  flag name  amount  to
  <dbl> <dbl> <chr>  <dbl> <chr>
1     1     1  a      21.2  a
2     1     0  b      19.4  a
3     2     1  a      21.8  d
4     2     1  c      18.7  d
5     2     0  d      19.6  d
6     3     0  b      20.6  b
7     3     1  c      17.1  b
8     3     1  c      19.1  b

mutate使用.$指的是整个tbl而不是组。我确定可以使用do来完成此操作,但是我对它的用法不是很熟悉,当我用上面的mutate调用替换它时,它给了我不想要的结构。

谢谢!

1 个答案:

答案 0 :(得分:0)

我们可以创建一个频次列

library(dplyr)
dta %>% 
   group_by(group, flag) %>% 
   mutate(n = n()) %>%
   group_by(group) %>%
   mutate(to = name[which(n ==1)[1]]) %>% 
   select(-n)
# A tibble: 8 x 5
# Groups:   group [3]
#  group  flag name  amount to   
#  <dbl> <dbl> <chr>  <dbl> <chr>
#1     1     1 a       21.2 a    
#2     1     0 b       19.4 a    
#3     2     1 a       21.8 d    
#4     2     1 c       18.7 d    
#5     2     0 d       19.6 d    
#6     3     0 b       20.6 b    
#7     3     1 c       17.1 b    
#8     3     1 c       19.1 b    

或者代替使用“ {group”和“ flag”分组,而是应用table来获取“ flag”的频率并提取与频率1对应的name

dta %>% 
    group_by(group) %>%
    mutate(to = name[which(table(factor(flag, 
             levels = 0:1))[as.character(flag)] == 1)])