按组汇总值,但保留原始数据

时间:2019-07-09 21:16:14

标签: r dplyr

我试图找出如何将values的{​​{1}}和属于category的{​​{1}}乘以因子file,同时还要保留原始数据。

library(dplyr)
df <- data.frame(ID = 1:20, values = runif(20), category = rep(letters[1:5], 4), file = as.factor(sort(rep(1:5, 4)))) 


   ID     values category file
1   1 0.65699229        a    1
2   2 0.70506478        b    1
3   3 0.45774178        c    1
4   4 0.71911225        d    1
5   5 0.93467225        e    1
6   6 0.25542882        a    2
7   7 0.46229282        b    2
8   8 0.94001452        c    2
9   9 0.97822643        d    2
10 10 0.11748736        e    2
11 11 0.47499708        a    3
12 12 0.56033275        b    3
13 13 0.90403139        c    3
14 14 0.13871017        d    3
15 15 0.98889173        e    3
16 16 0.94666823        a    4
17 17 0.08243756        b    4
18 18 0.51421178        c    4
19 19 0.39020347        d    4
20 20 0.90573813        e    4

这样

  • df[1,2]将被添加到df[2,2]的文件1的类别'ab'
  • df[6,2]将被添加到df[7,2]的文件2的类别'ab'

到目前为止,我有这个:

df %>% 
    filter(category %in% c('a' , 'b')) %>%
    group_by(file) %>% 
    summarise(values = sum(values))

问题

我想将求和值的类别更改为“ ab”,并将其附加到同一管道中的原始数据帧中。

所需的输出

   ID     values category file
1   1 0.65699229        a    1
2   2 0.70506478        b    1
3   3 0.45774178        c    1
4   4 0.71911225        d    1
5   5 0.93467225        e    1
6   6 0.25542882        a    2
7   7 0.46229282        b    2
8   8 0.94001452        c    2
9   9 0.97822643        d    2
10 10 0.11748736        e    2
11 11 0.47499708        a    3
12 12 0.56033275        b    3
13 13 0.90403139        c    3
14 14 0.13871017        d    3
15 15 0.98889173        e    3
16 16 0.94666823        a    4
17 17 0.08243756        b    4
18 18 0.51421178        c    4
19 19 0.39020347        d    4
20 20 0.90573813        e    4
21 21 1.25486225       ab    1
22 22 1.87216325       ab    2
23 23 1.36548126       ab    3

3 个答案:

答案 0 :(得分:1)

这将为您带来结果

function setValue(val) { a = val; websocket.send(a) }

代码示例中生成数据帧的代码是这个:

df %>% bind_rows(
  df %>% 
    filter(category %in% c('a' , 'b')) %>%
    group_by(file) %>% 
    mutate(values = sum(values), category = paste0(category,collapse='')) %>% 
    filter(row_number() == 1 & n() > 1)
) %>% mutate(ID = row_number())

现在让我们说您要对多个列求和,需要以向量形式提供列表:

df <- data.frame(ID = 1:20, values = runif(20), category = rep(letters[1:5], 4), file = as.factor(sort(rep(1:4, 5)))) 

答案 1 :(得分:1)

library(dplyr)

df1 %>% 
  filter(category %in% c('a' , 'b')) %>%
  group_by(file) %>%
  filter(n_distinct(category) > 1) %>% 
  summarise(values = sum(values)) %>%
  mutate(category="ab",
         ID=max(df1$ID)+1:n())  %>% 
  bind_rows(df1, .)
#> Warning in bind_rows_(x, .id): binding factor and character vector,
#> coercing into character vector
#> Warning in bind_rows_(x, .id): binding character and factor vector,
#> coercing into character vector
#>    ID     values category file
#> 1   1 0.62585921        a    1
#> 2   2 0.61865851        b    1
#> 3   3 0.05274456        c    1
#> 4   4 0.68156961        d    1
.
.
.
#> 19 19 0.43239411        d    5
#> 20 20 0.85886314        e    5
#> 21 21 1.24451773       ab    1
#> 22 22 0.99001810       ab    2
#> 23 23 1.25331943       ab    3

答案 2 :(得分:1)

data.table方法使用自连接来获取所有可能的两个字符的组合。

library(data.table)
setDT(df)

df_self_join <- df[df, on = .(file), allow.cartesian = T
                   ][category != i.category,
                     .(category = paste0(i.category, category), values = values + i.values, file)
                     ][order(category), .(ID = .I + nrow(df), values, category, file)]

rbindlist(list(df, df_self_join))

    ID     values category file
 1:  1 0.76984382        a    1
 2:  2 0.54311583        b    1
 3:  3 0.23462016        c    1
 4:  4 0.60179043        d    1
...
20: 20 0.03534223        e    5
21: 21 1.31295965       ab    1
22: 22 0.51666175       ab    2
23: 23 1.02305754       ab    3
24: 24 1.00446399       ac    1
25: 25 0.96910373       ac    2
26: 26 0.87795389       ac    4
#total of 80 rows

dplyr翻译非常接近

library(dplyr)
tib <- as_tibble(df)

inner_join(tib, tib, by = 'file')%>%
  filter(ID.x != ID.y)%>%
  transmute(category = paste0(category.x, category.y)
            , values = values.x + values.y
            , file)%>%
  arrange(category)%>%
  bind_rows(tib, .)%>%
  mutate(ID = row_number())%>%
  filter(category == 'ab') #filter added to show the "ab" files

# A tibble: 3 x 4
     ID values category file 
  <int>  <dbl> <chr>    <fct>
1    21  1.31  ab       1    
2    22  0.517 ab       2    
3    23  1.02  ab       3