R根据每个组中的一些规则获得一个值

时间:2019-07-02 03:46:34

标签: r group-by

我有一个数据框:

test = data.frame(short_name = rep(c('a','b','c'),each = 3),full_name = c('apple','ahora','aixin','bike','beber','boai','cerrar','cat','caocao'))

其中:

short_name   full_name
    a         apple
    a         ahora
    a         aixin
    b         bike
    b         beber
    b         boai
    c         cerrar
    c         cat
    c         caocao

我想基于short_name作为一个组来从full_name获取值,它可以是:

1)获取第一个元素(该组的第一行),在我的情况下为:

short_name   full_name
    a         apple
    b         bike
    c         cerrar

2)从全名中获取随机元素

3)根据某些规则获取元素,在我的情况下,您可能会注意到它们只是三种不同的语言:英语,西班牙语和中文;我可能会在这里放一个函数,告诉我它起源于什么语言,并为每个组选择西班牙语作为快捷方式的全名,但是该功能与本主题无关,所以我只想从每个组中获取最短的一种,并把如果长度相同,则break规则始终是该组中的第一个规则,结果应为:

short_name   full_name
    a         apple
    b         bike
    c         cat

您可以使用任何包(data.table,dplyr等)或自写方法,我希望看到不同的解决方案并获得最高效,最优雅的解决方案

根据最近的答案,我基于大数据(800万条记录)的计算是:

library(tictoc)
library(dplyr)
tic("dplyr slice1")
sale_data_detail_ly_slice1<-sale_data_detail_ly %>% group_by(prod_id) %>% slice(1)
toc()
dplyr slice1: 26.966 sec elapsed

tic("data.table")
sale_data_detail_ly_slice1 = sale_data_detail_ly[,.SD[1,],by = prod_id]
toc()
data.table: 501.416 sec elapsed

我可以看到很大的不同

3 个答案:

答案 0 :(得分:2)

我们可以通过'short_name'进行分组,并使用slice

获得第一行
library(dplyr)
test %>% 
   group_by(short_name) %>%
   slice(1)

或者获取随机元素

test %>%
  group_by(short_name) %>%
  slice(sample(row_number(), 1))

如果是最短的

test %>%
   group_by(short_name) %>%
   slice(which.min(nchar(as.character(full_name))))
# A tibble: 3 x 2
# Groups:   short_name [3]
#  short_name full_name
#  <fct>      <fct>    
#1 a          apple    
#2 b          bike     
#3 c          cat     

或使用summarise

test %>%
    group_by(short_name) %>%
    summarise(full_name = first(full_name))

test %>%
    group_by(short_name) %>%
    summarise(full_name = sample(full_name, 1))

对于data.table,选项为

library(data.table)
setDT(test)[test[, .I[1], .(short_name)]$V1]
setDT(test)[test[, .I[sample(seq_len(.N), 1)], .(short_name)]$V1]

答案 1 :(得分:2)

只要您能弄清楚如何计算每个组中所需的值,就可以使用group_bysummarise进行任何选择。一次性完成所有操作:

test %>%
    group_by(short_name) %>%
    summarise(
        first = first(full_name),
        random = sample(full_name, 1),
        # as.character needed here because full_name is currently
        #   a factor
        shortest = full_name[which.min(nchar(as.character(full_name)))]
    )

答案 2 :(得分:1)

一种data.table解决方案,与@akrun的解决方案略有不同:

test[, .SD[1,], by = short_name]

test[, .SD[sample(.N, 1),], by = short_name]

test[, .SD[which.min(nchar(as.character(full_name))),], by = short_name]