2015-12-01 111 views
0

因此,我有一個值在一定範圍內的列(請參見下文)。我已經使用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

解決方法是將聚合數據視爲查找表,然後使用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

我知道你明確表達了避免嵌套ifelse陳述的願望,所以原諒我在這裏使用一個陳述。但在我的辯護中,我們有一個解決方案,基本上重複使用相同的ifelse創建RangeAvg列,使用apply函數。我們還可以通過dplyr快速獲得平均值。

該解決方案還假設你只有ValueYear,首先,因爲我真的不知道你是怎麼到你的地方,例如,創造了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)) 

應該給你這樣的:

> df 
    Value Year  Range  Avg 
1  12 1906 1900-1910 15.333333 
2  15 1909 1900-1910 15.333333 
3  7 1911 1911-1920 6.666667 
4  22 1950 1941-1950 12.500000 
5  4 1917 1911-1920 6.666667 
6  9 1917 1911-1920 6.666667 
7  19 1902 1900-1910 15.333333 
8  1 1921 1921-1930 1.000000 
9  2 1931 1931-1940 2.000000 
10  3 1941 1941-1950 12.500000 
11  4 1951 1951-1960 4.000000 
12  5 1961 1961-1970 5.000000 
13  6 1971 1971-1980 6.000000 
14  7 1981 1981-1990 7.000000 
15  8 1991 1991-2000 15.333333 

我相信你可以做到這一點更快,用更少的代碼,但作爲交換條件,這是相當可讀的,你可以將它交給你的同事不得不做大量的評論。

相關問題