我有一个数据框:
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
我可以看到很大的不同
答案 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_by
和summarise
进行任何选择。一次性完成所有操作:
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]