【问题标题】:Replace numeric value with group minimum用组最小值替换数值
【发布时间】:2014-09-23 09:59:34
【问题描述】:

我希望根据分组变量 cat02 将 data.frame 列(下面的 ser04)中的所有数值 12345689 替换为 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


但它没有......

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

【问题讨论】:

  • ?ave;例如ave(olddf$ser04, olddf$cat02, FUN = function(x) ifelse(x == 123456789, min(x), x))

标签: r dataframe replace numeric


【解决方案1】:

@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))

【讨论】:

  • 谢谢! data.table 解决方案按预期工作,也在我的真实数据集和代码上工作。 (很遗憾,我没有足够的积分来投票给你的答案。)
【解决方案2】:

试试这个:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-02
    • 1970-01-01
    • 1970-01-01
    • 2020-07-26
    • 1970-01-01
    • 2017-11-07
    相关资源
    最近更新 更多