【问题标题】:Log Transform many variables in R with loop用循环记录转换R中的许多变量
【发布时间】:2020-04-27 23:44:41
【问题描述】:

我有一个数据框,其中包含一个用于诊断的二进制变量(第 1 列)和 165 个营养变量(第 2-166 列),用于 n=237。我们称这个数据集为 nutr_all。我需要创建 165 个新变量来获取每个营养变量的自然对数。所以,我想最终得到一个包含 331 列的数据框 - 第 1 列 = 诊断,第 2-166 列 = 营养变量,第 167-331 列 = 对数转换的营养变量。我希望这些变量取旧变量的名称,但末尾带有“_log”

我尝试过使用 for 循环和 mutate 命令,但是,我对 r 不是很精通,所以我有点挣扎。

for (nutr in (nutr_all_nomiss[,2:166])){
 nutr_all_log <- mutate(nutr_all, nutr_log = log(nutr) )
}

当我这样做时,它只会创建一个名为 nutr_log 的新变量。我知道我需要让 r 知道“nutr_log”中的“nutr”是 for 循环中的变量名,但我不确定如何。

【问题讨论】:

标签: r for-loop dplyr


【解决方案1】:

对于最近遇到此页面的任何人,dplyr::across() 是在 2020 年底推出的,它专为这项任务而构建 - 一次将相同的转换应用于许多列。

下面是一个简单的解决方案。

如果您需要选择要转换的列,请通过在 R 控制台中运行 ?tidyr_tidy_select 来查看 tidyselect 辅助函数。

library(tidyverse)
# create vector of column names
variable_names <- paste0("nutrient_variable_", 1:165)

# create random data for example
data_values <- purrr::rerun(.n = 165, 
                             sample(x=100, 
                                    size=237, 
                                    replace = T)) 

# set names of the columns, coerce to a tibble, 
# and add the diagnosis column
nutr_all <- data_values %>%
    set_names(variable_names) %>%
    as_tibble() %>% 
    mutate(diagnosis = 1:237) %>% 
    relocate(diagnosis, .before = everything())
    
# use across to perform same transformation on all columns 
# whose names contain the phrase 'nutrient_variable'
nutr_all_with_logs <- nutr_all %>%
    mutate(across(
        .cols = contains('nutrient_variable'),
        .fns = list(log10 = log10),
        .names = "{.col}_{.fn}"))

# print out a small sample of data to validate 
nutr_all_with_logs[1:5, c(1, 2:3, 166:168)]

个人而言,不是将所有列都添加到数据框中, 我宁愿制作一个仅包含 转换后的值,并更改列名:

logs_only <- nutr_all %>%
    mutate(across(
        .cols = contains('nutrient_variable'),
        .fns = log10)) %>% 
    rename_with(.cols = contains('nutrient_variable'),
                .fn = ~paste0(., '_log10'))
logs_only[1:5, 1:3]

【讨论】:

    【解决方案2】:

    我们可以使用mutate_at

    library(dplyr)
    nutr_all_log <- nutr_all_nomiss %>%
                        mutate_at(2:166, list(nutr_log = ~ log(.)))
    

    base R 中,我们可以直接在data.frame 上执行此操作

    nm1 <- paste0(names(nutr_all_nomiss)[2:166], "_nutr_log")
    nutr_all_nomiss[nm1] <- log(nutr_all_nomiss[nm1])
    

    【讨论】:

      【解决方案3】:

      在base R中,我们可以使用lapply

      nutr_all_nomiss[paste0(names(nutr_all_nomiss)[2:166], "_log")] <- lapply(nutr_all_nomiss[2:166], log)
      

      【讨论】:

        【解决方案4】:

        这是一个仅使用基础 R 的解决方案:

        首先,我将创建一个与您的数据集等效的数据集:

        nutr_all <- data.frame(
          diagnosis = sample(c(0, 1), size = 237, replace = TRUE)
        )
        
        for(i in 2:166){
          nutr_all[i] <- runif(n = 237, 1, 10)
          names(nutr_all)[i] <- paste0("nutrient_", i-1)
        }
        

        现在让我们创建新变量并将它们附加到数据框:

        nutr_all_log <- cbind(nutr_all, log(nutr_all[, -1]))
        

        这会处理名称:

        names(nutr_all_log)[167:331] <- paste0(names(nutr_all[-1]), "_log")
        

        【讨论】:

          【解决方案5】:

          使用 dplyr 的给定函数将完成您的任务,它可用于获取数据集中所有变量的日志转换,它还检查列是否具有 -ive 值。目前,在这个函数中它不会计算那些参数的日志,

          logTransformation<- function(ds)
          {
            # this function creats log transformation of dataframe for only varibles which are positive in nature
            # args:
              # ds : Dataset
          
            require(dplyr)
            if(!class(ds)=="data.frame" ) { stop("ds must be a data frame")}
          
            ds <- ds %>% 
              dplyr::select_if(is.numeric)
          
          
           # to get only postive variables
            varList<- names(ds)[sapply(ds, function(x) min(x,na.rm = T))>0] 
          
            ds<- ds %>% 
              dplyr::select(all_of(varList)) %>% 
              dplyr::mutate_at(
                   setNames(varList, paste0(varList,"_log")), log)
          )
            return(ds)
          }
          

          您可以将它用于您的案例:

          #assuming your binary variable has namebinaryVar
          nutr_allTransformed<- nutr_all %>% dplyr::select(-binaryVar) %>% logTransformation()
          
          

          如果你也想有负变量,替换 varlist 如下:

          varList<- names(ds)
          

          【讨论】:

            猜你喜欢
            • 2018-10-21
            • 2016-10-18
            • 2011-01-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多