将数值替换为组最小值

时间:2014-07-31 12:45:28

标签: r dataframe replace numeric

我希望将data.frame列(下面的ser04)中的所有数值12345689替换为每个分组变量cat02的最小值sero04。我试图在网上找到任何一个例子但是失败了。这是一次尝试使用for循环,它不会像希望的那样运行。

year <- c(1999,2000,2001,2002,2003,2004)
ser01 <- c(42,43,55,86,117,123)
ser02 <- c(67,87,93,56,217,336)
ser03 <- c(12,63,85,86,117,123)
ser04 <- c(55, 123456789, 15,123456789,187,223)
ser05 <- c(77, 48, 55,86,117,123)
ser06 <- c(63, 41, 35,88,19,98)
ser07 <- c(47, 49, 74,116,147,183)
cat01 <- c("aa", "bb", "cc", "aa", "aa","cc") 
cat02 <- c("ff", "ff", "gg", "gg", "hh","ff") 

olddf <- data.frame(year,ser01,ser02,ser03,ser04,ser05,ser06,ser07,cat01,cat02)
newdf <- NULL
newdf <- as.data.frame(newTable)

n <-  0
for(i in 1:6){
    for(j in 2:8){
        n <- n+1
        newdf[n, 1] <- as.numeric(olddf[i,j])
        if(newdf[n, 1]==123456789) newdf[n, 1]<- min(olddf[i,1:4])
    }
}

print(olddf)
print(newdf)

原始数据框看起来像

  year ser01 ser02 ser03     ser04 ser05 ser06 ser07 cat01 cat02
1 1999    42    67    12        55    77    63    47    aa    ff
2 2000    43    87    63 123456789    48    41    49    bb    ff
3 2001    55    93    85        15    55    35    74    cc    gg
4 2002    86    56    86 123456789    86    88   116    aa    gg
5 2003   117   217   117       187   117    19   147    aa    hh<
6 2004   123   336   123       223   123    98   183    cc    ff

,结果数据框看起来像是

  year ser01 ser02 ser03     ser04 ser05 ser06 ser07 cat01 cat02
1 1999    42    67    12        55    77    63    47    aa    ff
2 2000    43    87    63        55    48    41    49    bb    ff
3 2001    55    93    85        15    55    35    74    cc    gg
4 2002    86    56    86        15    86    88   116    aa    gg
5 2003   117   217   117       187   117    19   147    aa    hh
6 2004   123   336   123       223   123    98   183    cc    ff


但它没有...

[编辑:我注意到这段代码来自旧的尝试而且它没有引用组变量]

2 个答案:

答案 0 :(得分:2)

@alexis_laz ave解决方案很不错,但您也可以尝试data.tabledplyr来提高速度:

library(data.table)
newdf <- as.data.table(olddf)[, ser04 := ifelse(ser04 == 123456789,  min(ser04), ser04), by = cat02]


#    year ser01 ser02 ser03 ser04 ser05 ser06 ser07 cat01 cat02
# 1: 1999    42    67    12    55    77    63    47    aa    ff
# 2: 2000    43    87    63    55    48    41    49    bb    ff
# 3: 2001    55    93    85    15    55    35    74    cc    gg
# 4: 2002    86    56    86    15    86    88   116    aa    gg
# 5: 2003   117   217   117   187   117    19   147    aa    hh
# 6: 2004   123   336   123   223   123    98   183    cc    ff

dplyr

library(dplyr)
newdf <- 
  olddf %>%
  group_by(cat02) %>%
  mutate(ser04 = ifelse(ser04 == 123456789,  min(ser04), ser04))

答案 1 :(得分:1)

试试这个:

olddf$ser04[olddf$ser04==123456789] <-with(olddf, ave(ser04, cat02, FUN=min)[ser04==123456789])

olddf$ser04
#[1]  55  55  15  15 187 223