【问题标题】:Create a new column that normalizes by groups using dplyr使用 dplyr 创建一个按组标准化的新列
【发布时间】:2015-11-05 23:17:29
【问题描述】:

我有一个这样的df:

Level <- c('Level_1A','Level_1B','Level_1B','Level_1C','Level_1A','Level_1A','Level_1B','Level_1C','Level_1C')
PT <- c(50,100,150,20,30,40,60,80,90)
df <- data.frame(Level,PT)

我正在尝试在 df 中创建一个新列,该列具有 PT 列的标准化值并按级别分组

我想要的输出是

     Level  PT   NORM
1 Level_1A  50 1.0000
2 Level_1B 100 0.4444
3 Level_1B 150 1.0000
4 Level_1C  20 0.0000
5 Level_1A  30 0.0000
6 Level_1A  40 0.5000
7 Level_1B  60 0.0000
8 Level_1C  80 0.8571
9 Level_1C  90 1.0000

我正在尝试做这样的事情,但它没有按预期工作。

normalit<-function(m){
  (m - min(m))/(max(m)-min(m))
}

df$NORM <- df %>%
  group_by(Level) %>%
  summarise(PT = normalit(PT))

请就此提供一些意见。

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    最后一行应该是mutate(NORM = normalit(PT))而不是summarise(),赋值应该是df &lt;-而不是df$NORM &lt;-

    df <- df %>%
        group_by(Level) %>%
        mutate(NORM = normalit(PT))
    

    但您也可以通过使用 magrittr 复合赋值运算符来避免使用 df &lt;- df ...。这会将df 传递到表达式中,并一次性更新df

    library(magrittr)
    df %<>%
        group_by(Level) %>%
        mutate(NORM = normalit(PT))
    

    两者都将df作为

         Level    PT      NORM
        (fctr) (dbl)     (dbl)
    1 Level_1A    50 1.0000000
    2 Level_1B   100 0.4444444
    3 Level_1B   150 1.0000000
    4 Level_1C    20 0.0000000
    5 Level_1A    30 0.0000000
    6 Level_1A    40 0.5000000
    7 Level_1B    60 0.0000000
    8 Level_1C    80 0.8571429
    9 Level_1C    90 1.0000000
    

    您在 cmets 中询问 data.table,所以这里是这样做的代码。

    library(data.table)
    setDT(df)[, NORM := normalit(PT), by = Level]
    

    【讨论】:

    • 在大型数据集中执行相同操作时,data.table 是否比 dplyr 更快?
    • @Sharath - 可能是,是的。未经测试不能肯定地说。但是代码是library(data.table); setDT(df)[, NORM := normalit(PT), by = Level]
    • 感谢这些不同的技术。我将把这些应用到我更大的数据集上,看看哪个更适合我。 :-)
    • @Sharath -当然,没问题。乐于助人。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多