我写了一个函数来计算在某些条件下两年之间某些值的差异。因子水平必须完全匹配才能减去这些值。
虚拟数据:
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行中的值中减去,因为它是后一年并具有相同的属性(categoriesie = A,categorie = c,animal = G)。
以下功能正常。
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
很明显,因为几个if语句和&
运算符都需要它们。
是否有可能不对列名进行硬编码,而只是通过exsting的名称?
我想尽可能灵活。
非常感谢帮助
答案 0 :(得分:-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
并返回一个布尔值。