【问题标题】:R max of multiple categories [duplicate]多个类别的R max [重复]
【发布时间】:2018-01-28 05:43:31
【问题描述】:

我的数据有点像这样(当然还有更多行):

Age     Work Zone     SomeNumber
26      1          2.61
32      4          8.42
41      2          9.71
45      2          4.14
64      3          6.04
56      1          5.28
37      4          7.93

我想获得每个年龄或低于每个年龄的每个区域的最大 SomeNumber。 SomeNumber 随着年龄的增长而增加,所以我预计 2 区中 32 岁以下的最高 SomeNumber 是 31 岁的人,但实际上可能是 27 岁的人。

为此,我编写了一个嵌套的 for 循环:

for(i in zonelist){
  temp = data[data$zone==i,]
  for(j in 1:max(data$age)){
    temp.lessequal=c(temp.lessequal,max((temp[temp$Age<=j,])$SomeNumber))
  }
  #plot temp.lessequal or save it at this point
}

这当然非常慢。我怎样才能更快地做到这一点?我查看了一次按两列排序的 order 函数,但这并不能让我取每个组的最大值。

【问题讨论】:

  • @Sathish 如果我理解正确,这个问题对我来说似乎并不重复。可能是我错了。
  • 我的回答与上面发布的链接中的解决方案之一完全相同

标签: r loops dataframe categories


【解决方案1】:

数据:

df1 <- read.table(text='Age Work_Zone  SomeNumber
26      1          2.61
                   32      4          8.42
                   41      2          9.71
                   45      2          4.14
                   64      3          6.04
                   56      1          5.28
                   37      4          7.93', 
                   header = TRUE)

代码:

df2 <- with( df1, df1[ Age <= 32, ] )  # extract rows with Age <= 32
# get maximum of someNumber by aggregating with work_zone and then merging with df1 to combine the age column
merge(aggregate(SomeNumber ~ Work_Zone, data = df2, max), df2) 
#   Work_Zone SomeNumber Age
# 1         1       2.61  26
# 2         4       8.42  32

【讨论】:

  • 我不认为 OP 在任何地方都对 32 进行硬编码,而是将其用作示例。他/她正在寻找当前行的年龄
【解决方案2】:

似乎 OP 正在根据特定列 (Age) 上的 &lt;= 条件寻找 max 值。

在这种情况下使用sqldf 非常方便,可以解释逻辑。一种解决方案可能是:

# Data 
df <- read.table(text = "Age     Work_Zone     SomeNumber
26      1          2.61
32      4          8.42
41      2          9.71
45      2          4.14
64      3          6.04
56      1          5.28
37      4          7.93", header = T, stringsAsFactors = F)

library(sqldf)
df3 <- sqldf("select df1.Work_Zone, df1.Age, max(df2.SomeNumber) from df df1 
       inner join df df2 on df1.Work_Zone = df2.Work_Zone 
       WHERE df2.Age <= df1.Age 
       GROUP BY df1.Work_Zone, df1.Age")

# Result:
#   Work_Zone Age max(df2.SomeNumber)
# 1         1  26                2.61
# 2         1  56                5.28
# 3         2  41                9.71
# 4         2  45                9.71
# 5         3  64                6.04
# 6         4  32                8.42
# 7         4  37                8.42

【讨论】:

    【解决方案3】:

    使用库data.table,您可以选择小于要求年龄的行,然后为每个工作区输出max(somenumber) 及其各自的年龄,即按工作区分组。

    library(data.table)
    setDT(df1)[Age<=32,.(max(SomeNumber),Age),by=Work_Zone]
       Work_Zone   V1 Age
    1:         1 2.61  26
    2:         4 8.42  32
    

    【讨论】:

    • 感谢您提供此代码 sn-p,它可能会提供一些有限的即时帮助。 proper explanation would greatly improve its long-term value 通过展示为什么这是一个很好的解决问题的方法,并将使其对未来有其他类似问题的读者更有用。请edit您的回答添加一些解释,包括您所做的假设。
    猜你喜欢
    • 2015-09-04
    • 2015-02-10
    • 2019-09-06
    • 2016-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多