【问题标题】:scale/normalize columns by group按组缩放/标准化列
【发布时间】:2015-01-13 00:40:37
【问题描述】:

我有一个如下所示的数据框:

  Store Temperature Unemployment Sum_Sales
1     1       42.31        8.106   1643691
2     1       38.51        8.106   1641957
3     1       39.93        8.106   1611968
4     1       46.63        8.106   1409728
5     1       46.50        8.106   1554807
6     1       57.79        8.106   1439542

对于每个“商店”,我想规范化/缩放两列(“Sum_sales”和“Temperature”)。

期望的输出:

  Store Temperature Unemployment Sum_Sales
1     1       1.000        8.106   1.00000
2     1       0.000        8.106   0.94533
3     1       0.374        8.106   0.00000
4     2       0.012        8.106   0.00000
5     2       0.000        8.106   1.00000
6     2       1.000        8.106   0.20550

这是我创建的规范化函数:

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

我尝试过的:

df2 <- df %.%
  group_by('Store') %.%
  summarise(Temperature = normalit(Temperature), Sum_Sales = normalit(Sum_Sales)))

任何建议/帮助将不胜感激。谢谢。

【问题讨论】:

  • 您的结果中有一个unemployment 列。每个商店都一样吗>
  • 是的.. 抱歉没有指定

标签: r dplyr scale plyr


【解决方案1】:

使用 dplyr 1.0.0 更新

@Vincent 的解决方案可以用提供across 的新 dplyr 语法编写:

df %>%
    group_by(Store) %>%
    mutate(across(c(Temperature, Sum_Sales), normalit)

如果您不记得normalit 的定义,您可以使用scales 包,该包提供了rescale 函数,该函数使用默认参数进行规范化:

df %>%
    group_by(Store) %>%
    mutate(across(c(Temperature, Sum_Sales), scales::rescale)

【讨论】:

    【解决方案2】:

    问题是您使用了错误的 dplyr 动词。 Summarize 将为每个变量的每个组创建一个结果。你想要的是变异。变异改变变量并返回与原始长度相同的结果。见http://cran.rstudio.com/web/packages/dplyr/vignettes/dplyr.html。以下两种使用 dplyr 的方法:

    df %>%
        group_by(Store) %>%
        mutate(Temperature = normalit(Temperature), Sum_Sales = normalit(Sum_Sales))
    
    df %>%
        group_by(Store) %>%
        mutate_each(funs(normalit), Temperature, Sum_Sales)
    

    注意:您的数据和所需结果之间的 Store 变量不同。我认为@jlhoward 得到了正确的数据。

    【讨论】:

    • 我收到一个错误“找不到函数 normalit”,我需要为此安装一些软件包吗? @文森特
    • 查看 OPs normalit 函数
    • 小插图链接已失效
    • 链接已修复。谢谢@AlexReynolds
    【解决方案3】:

    这是一个 data.table 解决方案。我稍微更改了您的示例以具有两种类型的商店。

    df <- read.table(header=T,text="Store Temperature Unemployment Sum_Sales
    1     1       42.31        8.106   1643691
    2     1       38.51        8.106   1641957
    3     1       39.93        8.106   1611968
    4     2       46.63        8.106   1409728
    5     2       46.50        8.106   1554807
    6     2       57.79        8.106   1439542")
    
    library(data.table)
    DT <- as.data.table(df)
    DT[,list(Temperature=normalit(Temperature),Sum_Sales=normalit(Sum_Sales)),
        by=list(Store,Unemployment)]
    #    Store Unemployment Temperature Sum_Sales
    # 1:     1        8.106  1.00000000 1.0000000
    # 2:     1        8.106  0.00000000 0.9453393
    # 3:     1        8.106  0.37368421 0.0000000
    # 4:     2        8.106  0.01151461 0.0000000
    # 5:     2        8.106  0.00000000 1.0000000
    # 6:     2        8.106  1.00000000 0.2055018
    

    请注意,如果 stoer 只有 1 行,您的规范化会出现问题。

    【讨论】:

    • 很好的解决方案@jlhoward。我假设 Unemployment 已添加到 by 列表中,因此它不会被删除。只是出于好奇,如果不是每个商店的失业率都保持不变,您将如何保持失业率仍能达到预期的结果?
    • OP 希望每个商店有 1 行。如果给定商店的失业率不是恒定的,您会使用什么值?
    • 我只是想知道每个商店是否有三行(如 OP 所需的输出),如果不通过 by=list(),您将如何保持失业。
    猜你喜欢
    • 1970-01-01
    • 2015-12-11
    • 1970-01-01
    • 2015-03-04
    • 2020-07-02
    • 2017-10-13
    • 2019-01-21
    • 2021-05-30
    相关资源
    最近更新 更多