为范围内的每个值应用一个数字

时间:2015-12-01 03:52:21

标签: r

所以我有一个包含值的列,这些列在几年的某些范围内(见下文)。我使用aggregate()获得了每个范围的平均值。但是,当我尝试为每个值应用此平均数时,我收到错误。例如,对于1900-1910范围内的每个值,我希望该范围的平均值出现在该行的“平均”列中

我能得到什么:

Range      Avg
1900-1910  15.33
1911-1920   6.67
....
1941-1950  22.00 

想要:

Value Year   Range       Avg
12    1906   1900-1910   15.33
15    1909   1900-1910   15.33
7     1911   1911-1920    6.67
22    1950   1941-1950   22.00
4     1917   1911-1920    6.67
9     1917   1911-1920    6.67
19    1902   1900-1910   15.33

我能够获得每个范围的平均值,但我无法弄清楚如何将范围的平均值应用于每个特定值。我唯一能想到的是一堆嵌套的ifelse()语句,但这似乎太乏味了。例如:

d$Avg<-ifelse(Range=="1900-1910",15.33,
       ifelse(Range=="1911-1920",6.67,
       ...etc))

有没有办法可以加快这个过程,而不是使用一堆嵌套的ifelse语句?

2 个答案:

答案 0 :(得分:2)

解决方案是将聚合数据视为查找表,然后使用merge获取所需的数据集。

因此,如果汇总数据为lookupdf,那么我们可以像这样使用merge

final_df <- merge(d, lookupdf, by=c("Range"))

用于演示此示例的示例代码:

d <- data.frame(Year=rep(1900+c(1:20), 20),
           Value=runif(400, 1, 20))

d$Range <- ifelse(d$Year <= 1910, "1900-1910", "1911-1920")

library(dplyr)
# generate the aggregation; should be same as what you have above.
lookupdf <- d %>% group_by(Range) %>% summarise(Avg=mean(Value))

# base R version
final_df <- merge(d, lookupdf, by=c("Range"))

输出:

> head(final_df[final_df$Year %in% c(1910, 1911),])
   Year     Value     Range      Avg
10 1910 18.643543 1900-1910 11.17740
11 1911  1.142544 1911-1920 10.18118
30 1910 11.187802 1900-1910 11.17740
31 1911  9.887889 1911-1920 10.18118
50 1910  5.316916 1900-1910 11.17740
51 1911 15.365103 1911-1920 10.18118

答案 1 :(得分:1)

我知道你明确表达了避免嵌套ifelse语句的愿望,所以原谅我在这里使用一个。但在我的辩护中,我们有一个解决方案,基本上重用相同的ifelse来创建RangeAvg列,使用apply函数。我们也可以使用dplyr快速获取平均值。

此解决方案还假设您只有ValueYear开头,因为我不确定您是如何到达您所在的位置,例如创建{{1} }列。所以我从零开始。

首先编写一个函数来定义Range

Range

然后,应用它:

library(dplyr)

get_range <- function(number){   #<-- takes in percentile
  ans <-
    if ( (number >= 1900) & ( number <= 1910) ) {
      "1900-1910"
    } else if ( (number > 1910 ) & ( number <= 1920) ) {
      "1911-1920"
    } else if ( (number > 1920 ) & ( number <= 1930) ) {
      "1921-1930"
    } else if ( (number > 1930 ) & ( number <= 1940) ) {
      "1931-1940"
    } else if ( (number > 1940 ) & ( number <= 1950) ) {
      "1941-1950"
    } else if ( (number > 1950 ) & ( number <= 1960) ) {
      "1951-1960"
    } else if ( (number > 1960 ) & ( number <= 1970) ) {
      "1961-1970"
    } else if ( (number > 1970 ) & ( number <= 1980) ) {
      "1971-1980"
    } else if ( (number > 1980 ) & ( number <= 1990) ) {
      "1981-1990"
    } else if ( (number > 1990 ) & ( number <= 2000) ) {
      "1991-2000"
      } else {
      "NA"
    }
  return(ans)
}

接下来,使用df$Range <- sapply(df$Year, function(x) get_range(x)) 获取您的汇总值并存储在单独的数据框中。

dplyr

修改上述相同的功能以处理平均值

df_Avg <- df %>%
  group_by(Range) %>%
  summarise(Avg =  mean(Value))

...最后,应用该功能。

get_avg <- function(number){
  ans <-
    if ( (number >= 1900) & ( number <= 1910) ) {
      df_Avg$Avg[1]
    } else if ( (number > 1910 ) & ( number <= 1920) ) {
      df_Avg$Avg[2]
    } else if ( (number > 1920 ) & ( number <= 1930) ) {
      df_Avg$Avg[3]
    } else if ( (number > 1930 ) & ( number <= 1940) ) {
      df_Avg$Avg[4]
    } else if ( (number > 1940 ) & ( number <= 1950) ) {
      df_Avg$Avg[5]
    } else if ( (number > 1950 ) & ( number <= 1960) ) {
      df_Avg$Avg[6]
    } else if ( (number > 1960 ) & ( number <= 1970) ) {
      df_Avg$Avg[7]
    } else if ( (number > 1970 ) & ( number <= 1980) ) {
      df_Avg$Avg[8]
    } else if ( (number > 1980 ) & ( number <= 1990) ) {
      df_Avg$Avg[9]
    } else if ( (number > 1990 ) & ( number <= 2000) ) {
      df_Avg$Avg[1]
    } else {
      "NA"
    }
  return(ans)
}

应该给你这个:

df$Avg <- sapply(df$Year, function(x) get_avg(x))

我确信你可以用更少的代码更快地做到这一点,但作为交换,这是相当可读的,你可以把它交给你的同事,不得不做大量的评论。