所以我有一个包含值的列,这些列在几年的某些范围内(见下文)。我使用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语句?
答案 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
来创建Range
和Avg
列,使用apply函数。我们也可以使用dplyr
快速获取平均值。
此解决方案还假设您只有Value
和Year
开头,因为我不确定您是如何到达您所在的位置,例如创建{{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))
我确信你可以用更少的代码更快地做到这一点,但作为交换,这是相当可读的,你可以把它交给你的同事,不得不做大量的评论。