2015-12-15 6 views
-1

Я написал функцию, которая вычисляет разницу какого-либо значения в течение двух лет при определенных условиях. Уровни факторов должны соответствовать точно, чтобы вычесть значения.R - Динамические условия в функции

фиктивные данные:

df <- data.frame(year=rep(2001:2003,each=4), 
       country=rep(c("A","B"),6), 
       categorie=rep(letters[3:6],3), 
       animal=rep(LETTERS[7:10],3), 
       value=sample(1:10,12,replace=T)) 

df 
year country categorie animal value 
1 2001  A   c  G  9 
2 2001  B   d  H  2 
3 2001  A   e  I  8 
4 2001  B   f  J  7 
5 2002  A   c  G  4 
6 2002  B   d  H  3 
7 2002  A   e  I  4 
8 2002  B   f  J  4 
9 2003  A   c  G 10 
10 2003  B   d  H  1 
11 2003  A   e  I  4 
12 2003  B   f  J 10 

Значение в строке 5 следует вычесть из значения в строке 1, потому что это последующий год и имеет те же атрибуты (Категория = А, Категория = с, животное = Г).

Функция ниже работает нормально.

calc.change <- function(df, cols){ 
    for(i in cols){ 
    p <- vector(mode="numeric", length = nrow(df)) 
    for(k in seq_len(nrow(df))){ 
     #first year is NA because no difference can be calculated 
     if(df$year[k]==min(df$year[df$country==df$country[k] & 
     df$categorie==df$categorie[k] & df$animal==df$animal[k]])){ 
     p[k] <- NA 
     } else { 
     p[k] <- df[[i]][k]-df[[i]][df$year==df$year[k]-1 & df$categorie==df$categorie[k] 
           & df$animal==df$animal[k] & df$country==df$country[k]] 
     } 
    } 
    df <- cbind(df, p) 
    names(df)[names(df)=="p"] <- paste0(i,".change") 
    } 
    return(df) 
} 

foo <- calc.change(df, "value") 


foo 
year country categorie animal value value.change 
1 2001  A   c  G  4   NA 
2 2001  B   d  H  4   NA 
3 2001  A   e  I  9   NA 
4 2001  B   f  J  1   NA 
5 2002  A   c  G  2   -2 
6 2002  B   d  H  3   -1 
7 2002  A   e  I  2   -7 
8 2002  B   f  J  5   4 
9 2003  A   c  G  4   2 
10 2003  B   d  H 10   7 
11 2003  A   e  I 10   8 
12 2003  B   f  J  5   0 

Однако функция больше не работает, если один из столбцов country categorie или animal отсутствует.

foobar <- aggregate(value ~ year+country, df, mean) 

head(foobar) 
    year country value 
1 2001  A 6.5 
2 2002  A 2.0 
3 2003  A 7.0 
4 2001  B 2.5 
5 2002  B 4.0 
6 2003  B 7.5 

calc.change(foobar, value) #gives an error 

Это понятно, потому что они требуют несколько, если-заявления и & операторов. Можно ли не жестко указывать имена столбцов, а только передавать exsting? Я хотел бы сделать его максимально гибким.

Помощь будет весьма признателен

+0

Можете ли вы добавить желаемый результат на основе ввода? – Heroka

ответ

-1

Вы можете использовать функции высшего порядка в R. То есть вы можете передать функцию в функцию

test <- function(df,k) 
    df$year[k]==min(df$year[df$country==df$country[k] & 
      df$categorie==df$categorie[k] & df$animal==df$animal[k]]) 



calc.change <- function(df, cols,test){ 
    for(i in cols){ 
    p <- vector(mode="numeric", length = nrow(df)) 
    for(k in seq_len(nrow(df))){ 
     #first year is NA because no difference can be calculated 
     if(test(df,k){ 
     p[k] <- NA 
     } else { 
     p[k] <- df[[i]][k]-df[[i]][df$year==df$year[k]-1 & df$categorie==df$categorie[k] 
           & df$animal==df$animal[k] & df$country==df$country[k]] 
     } 
    } 
    df <- cbind(df, p) 
    names(df)[names(df)=="p"] <- paste0(i,".change") 
    } 
    return(df) 
} 

calc.change(df, "value",test) 

Теперь вы можете заменить test любой функции, что така dataframe и integary и возвращать логическое значение.

Смежные вопросы