首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >获取多个字符串值R的最小值

获取多个字符串值R的最小值
EN

Stack Overflow用户
提问于 2014-07-31 21:50:50
回答 3查看 95关注 0票数 1

我在一个青少年犯罪数据库工作,需要报告开始犯罪的年龄。我目前有犯罪的姓名和年龄,许多对象都是惯犯,我需要隔离最早的犯罪年龄。我可以逐行浏览(31,000+行),但我希望有更简单的方法来实现这一点。

我所拥有的

代码语言:javascript
复制
Subject A      15
Subject A      17
Subject A      17
Subject B      11
Subject B      12
Subject B      15
Subject B      17

我需要的是

代码语言:javascript
复制
Subject A      15 
Subject A      15
Subject A      15
Subject B      11
Subject B      11
Subject B      11
Subject B      11
EN

回答 3

Stack Overflow用户

发布于 2014-07-31 22:00:41

以下是几种实现此目的的方法:

代码语言:javascript
复制
# your sample data
df <- read.table(header=F, text="
Subject_A      15
Subject_A      17
Subject_A      17
Subject_B      11
Subject_B      12
Subject_B      15
Subject_B      17", stringsAsFactors = FALSE)

names(df) <- c("Subject", "Age") # add some column names

使用base R ave

代码语言:javascript
复制
df$Min_Age <- ave(df$Age, df$Subject, FUN = min)

或者使用dplyr

代码语言:javascript
复制
library(dplyr)

df <- df %>% 
  group_by(Subject) %>%
  mutate(Min_Age = min(Age))

或者使用data.table

代码语言:javascript
复制
library(data.table)

setDT(df)[, Min_Age := min(Age), by = Subject]

如果您只想用最小值替换Age列,而不想创建新列,则可以用现有的列名Age替换每个解决方案中的Min_Age条目。

编辑:这里有一个小的基准测试(不包括for循环,因为我不认为应该这样做)。

代码语言:javascript
复制
df <- data.frame(Subject = sample(LETTERS, 1e4, TRUE), 
                 Age = sample(10:99, 1e4, TRUE))

dt <- as.data.table(df)

library(microbenchmark)
library(doBy)

microbenchmark(
  ave1 = {ave(df$Age, df$Subject, FUN = min)},
  ave2 = {with(df, ave(Age, Subject, FUN = min))},
  dplyr1 = {df %>% group_by(Subject) %>% mutate(Min_Age = min(Age))},
  dplyr2 = {df%>% group_by(Subject) %>% arrange(Subject,Age) %>% mutate(Min_Age=Age[1])},
  data.table = {dt[, Min_Age := min(Age), by = Subject]},
  doBy = {summaryBy(Age ~ Subject, df, FUN = min, full.dimension = TRUE)},
  lapply = {with(df, unsplit(lapply(split(Age, Subject), min), df[[1]]))},
  unit = "relative", 
  times = 100)

# Unit: relative
#      expr       min        lq    median        uq       max neval
#ave1        1.022080  1.015667  1.029203  1.040314  3.017348   100
#ave2        1.000000  1.000000  1.000000  1.000000  1.000000   100
#dplyr1      1.158047  1.168557  1.207314  1.229463  1.075171   100
#dplyr2      4.452059  4.408963  4.424622  4.374746  3.692858   100
#data.table  1.143520  1.212317  1.265719  1.280680  3.265307   100
#doBy       18.047627 17.584799 17.609035 17.470075 19.118029   100
#lapply      1.164438  1.120205  1.117074  1.116633  3.186735   100

因此,base R的ave在这种情况下执行得很好,尽管结果可能会根据实际数据中的组大小而变化。

更新:基准测试中包含doBylapply版本。

票数 2
EN

Stack Overflow用户

发布于 2014-07-31 22:58:24

您可以使用doBy包中的summaryBy

代码语言:javascript
复制
> library(doBY)
> summaryBy(V2~V1, data = dat, FUN = min, full.dimension = TRUE)

或者使用splitunsplit的另一种方式

代码语言:javascript
复制
> s <- with(dat, split(V2, V1))
> dat$V2 <- unsplit(lapply(s, min), dat$V1)

另一个是使用ddply

代码语言:javascript
复制
> library(plyr)
> ddply(dat, .(V1), summarize, min = rep(min(V2), length(V2)))

dat在哪里

代码语言:javascript
复制
dat <- read.table(text = "SubjectA      15
SubjectA      17
SubjectA      17
SubjectB      11
SubjectB      12
SubjectB      15
SubjectB      17")

因为我们要对所有东西进行基准测试,所以R是我的三个中最快的。

代码语言:javascript
复制
> f <- function(){
      dat$V2 <- with(dat, unsplit(lapply(split(V2, V1), min), dat[[1]]) )
      dat
  }
> microbenchmark(f())
# Unit: microseconds
#  expr     min       lq   median       uq     max neval
#    f() 108.788 110.4575 111.0665 112.108 251.813   100
票数 1
EN

Stack Overflow用户

发布于 2014-07-31 22:00:17

您的数据是在包含2列的数据帧中,还是在这些单独的字符串中?

如果它是一个有2列的数据帧(假设列名是" name“和"age"),并且该数据帧的变量名是”column“:

代码语言:javascript
复制
split.crime <- split(crime, name)
result.df <- data.frame()
for (sub.df in split.crime) {
   min.age <- min(df$age)
   new.sub.df <- data.frame(name = sub.df$name, age = min.age)
   result.df <- rbind(result.df, new.sub.df) }
rm(split.crime)
result.df

这是一个非常透明和缓慢的版本。我确信它可以用更少的代码和更快的速度来完成。对于您的数据帧大小,它应该工作得很好。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25060629

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档