r中的选择性缩放函数使用不同的数据框进行缩放

Posted

技术标签:

【中文标题】r中的选择性缩放函数使用不同的数据框进行缩放【英文标题】:selective scaling function in r using a different data frame to scale 【发布时间】:2022-01-21 16:08:21 【问题描述】:

我是 R 的新手。我希望编写一个函数来缩放我的数据框中的所有数字列,除了特定的数字列(在下面的示例中,我不想缩放列“估计”)。由于使用此函数的特定上下文,我实际上想使用另一个数据框来缩放数据。下面是一个失败的尝试。在这个尝试中 original.df 表示需要缩放的数据框,scaling.data 表示用于缩放的数据。我试图将数字 original.df 列集中在相应 scaling.data 列的平均值上,然后除以 scaling.data 列的 2 个标准差。

对于工作解决方案可能不是必不可少的其他信息:

这个函数将嵌套在一个更大的函数中。在较大的函数中有一个称为 predictors 的参数,它表示需要包含在新数据框中的列名称,并且在缩放数据框中也可以找到。这可能是用于迭代缩放函数的向量,尽管这不是必需的。 (注意:此向量包括引用字符和数字列的列名,我再次希望该函数仅缩放数字列。最终产品应包括 original.df 中未缩放的“估计”列)。

> predictors
[1] "color"  "weight" "height" "length"
    
>original.df
    color weight height length estimate
    1    red     10     66     40        5
    2    red     12     60     41        7
    3 yellow     12     67     48        9
    4   blue     15     55     36       10
    5 yellow     21     54     48        7
    6    red     12     54     43        5
    7    red     11     38     36        6
            
     
  >scale.data
     color weight height length estimate
    1    red     11     55     41        7
    2    red     13     67     39        9
    3 yellow     12     67     46       11
    4   blue     16      8     37        5
    5 yellow     23     10     47        9
    6    red     17     11     41       10
    7    red     16     13     37       13
                
 

    scale2sd<-function(variable)
         original.df[[variable]]<-((original.df[[variable]]) - mean(scaling.data[[variable]],na.rm=TRUE))/(2*sd(scaling.data[[variable]], na.rm=TRUE))
                            return(original.df[[variable]])
                          
        
     new.df<-original.df %>%mutate_at((!str_detect(names(.),"estimate")&is.numeric),scale)

我需要结果是全新的缩放数据框。

非常感谢您的时间和想法。

【问题讨论】:

【参考方案1】:

使用基本 R 的一种方式。代码中的注释。谢谢 Nelson,提供数据 +1

df <- read.table(text="color weight height length estimate
    1    red     10     66     40        5
    2    red     12     60     41        7
    3 yellow     12     67     48        9
    4   blue     15     55     36       10
    5 yellow     21     54     48        7
    6    red     12     54     43        5
    7    red     11     38     36        6", head=T)

scale_df <- read.table(text=" color weight height length estimate
    1    red     11     55     41        7
    2    red     13     67     39        9
    3 yellow     12     67     46       11
    4   blue     16      8     37        5
    5 yellow     23     10     47        9
    6    red     17     11     41       10
    7    red     16     13     37       13", head=T)

## add reference and scaling df as arguments
scale2sd <- function(ref, scale_by, variable) 
  ((ref[[variable]]) - mean(scale_by[[variable]], na.rm = TRUE)) / (2 * sd(scale_by[[variable]], na.rm = TRUE))

predictors <- c("color", "weight", "height", "length")
## this is to get all numeric columns that are part of your predictor variables
df_to_scale <- Filter(is.numeric, df[predictors])
## create a named vector. This is a bit awkward but it makes it easier to select
## the corresponding items in the two data frames, 
## and then replace the original columns 
num_vars <- setNames(names(df_to_scale), names(df_to_scale))                      

## this is the actual scaling job - 
## use the named vector for looping over the selected columns 
## then assign it back to the selected columns
df[num_vars] <- lapply(num_vars, function(x) scale2sd(df, scale_df, x))

df
#>    color      weight     height      length estimate
#> 1    red -0.67259271 0.58130793 -0.14222363        5
#> 2    red -0.42479540 0.47561558 -0.01777795        7
#> 3 yellow -0.42479540 0.59892332  0.85334176        9
#> 4   blue -0.05309942 0.38753862 -0.64000632       10
#> 5 yellow  0.69029252 0.36992323  0.85334176        7
#> 6    red -0.42479540 0.36992323  0.23111339        5
#> 7    red -0.54869405 0.08807696 -0.64000632        6

【讨论】:

【参考方案2】:

我们可以执行以下操作(我使用的是 dplyr 1.0.7,但任何 >= 1.0.0 都可以):

创建一个可缩放的函数

scale_to_sd <- function(other_df, target)
      
      mean(other_df[,target], na.rm=TRUE) / 
        (2*sd(other_df[, target], na.rm=TRUE))  
    

如果您只需要严格的numeric 列并且需要排除某些列,我们可以使用matches,它提供了比contains 更大的灵活性,例如

df %>% 
   mutate(across(!matches("estimate|height") & where(is.numeric),
                 ~  .x - scale_to_sd(scale_df,cur_column()))) 
  

以上将缩放除估计或高度之外的任何内容。人们可以玩转正则表达式。

    color    weight height   length estimate
1    red  8.088421     66 34.87995        5
2    red 10.088421     60 35.87995        7
3 yellow 10.088421     67 42.87995        9
4   blue 13.088421     55 30.87995       10
5 yellow 19.088421     54 42.87995        7
6    red 10.088421     54 37.87995        5
7    red  9.088421     38 30.87995        6

原创

df %>% 
  mutate(across(contains("estimate") & where(is.numeric),
                ~  .x - scale_to_sd(scale_df,cur_column()))) 

跨目标列应用函数

 df %>% 
       mutate(across(contains("estimate"),
                     ~  .x - scale_to_sd(scale_df,cur_column()))) 

结果

        color weight height length estimate
    1    red     10     66     40 3.248164
    2    red     12     60     41 5.248164
    3 yellow     12     67     48 7.248164
    4   blue     15     55     36 8.248164
    5 yellow     21     54     48 5.248164
    6    red     12     54     43 3.248164
    7    red     11     38     36 4.248164

使用的数据:


df <- read.table(text="color weight height length estimate
    1    red     10     66     40        5
    2    red     12     60     41        7
    3 yellow     12     67     48        9
    4   blue     15     55     36       10
    5 yellow     21     54     48        7
    6    red     12     54     43        5
    7    red     11     38     36        6", head=T)

scale_df <- read.table(text=" color weight height length estimate
    1    red     11     55     41        7
    2    red     13     67     39        9
    3 yellow     12     67     46       11
    4   blue     16      8     37        5
    5 yellow     23     10     47        9
    6    red     17     11     41       10
    7    red     16     13     37       13", head=T)

【讨论】:

感谢您的回答!我不想缩放列“估计”,而是缩放所有其他数字列。我认为您的答案仅适用于“估计”列。有没有办法将您的解决方案表达为缩放除“估计”之外的所有数字?另外,有没有办法列出多个不缩放的列(例如,除重量和估计之外的 df 中的所有内容)?再次感谢您。 我现在在移动设备上,明天再看一遍。您可以仅使用where(is.numeric) 来扩展所有内容,并且可以使用! 否定contains,所以它不会。您还可以使用 matches 并提供带有否定的 RegEx,例如!matches("a" | "b")。如果您在明天之前需要快速解决方案,可以尝试这些。答案基于样本数据。 @ksweet,检查编辑。

以上是关于r中的选择性缩放函数使用不同的数据框进行缩放的主要内容,如果未能解决你的问题,请参考以下文章

R语言层次聚类(hierarchical clustering):使用scale函数进行特征缩放hclust包层次聚类(创建距离矩阵聚类绘制树状图dendrogram,在树状图上绘制红色矩形框)

R语言使用caret包的preProcess函数进行数据预处理:对所有的数据列进行最小最大缩放设置method参数为range

R语言生成仿真的3D高斯簇数据集使用scale函数进行数据缩放并使用KMeans进行聚类分析数据反向缩放并比较聚类生成的中心和实际数据的中心的差异预测新的数据所属的聚类簇

R语言使用magick包的image_scale函数对图像进行缩放(resize)可以自定义从宽度或者高度角度进行缩放

R语言使用Rtsne包进行TSNE分析:通过数据类型筛选数值数据scale函数进行数据标准化缩放提取TSNE分析结果合并到原dataframe中(tSNE with Rtsne package)

R语言使用caret包的predict函数对测试数据集进行数据预处理(和训练集的处理方式保持一致):缺失值填充数值变量最小最大缩放因子变量独热编码等