【问题标题】:Removing columns based on a vector of names in R根据R中的名称向量删除列
【发布时间】:2020-02-04 08:07:33
【问题描述】:

我有一个名为DATAdata.frame。使用 BASE R,我想知道如何删除 DATA 中名为以下任何变量的变量:ar = c("out", "Name", "mdif" , "stder" , "mpre")

目前,我使用DATA[ , !names(DATA) %in% ar],但这会删除不需要的变量,但它会再次创建一些以.1 为后缀的新变量。

提取后,是否可以只删除后缀?

注意1:我们无法访问r,唯一的输入是DATA

注意2:这是玩具数据,感谢提供功能解决方案。

r <- list(
 data.frame(Name = rep("Jacob", 6), 
           X = c(2,2,1,1,NA, NA), 
           Y = c(1,1,1,2,1,NA), 
           Z = rep(3, 6), 
         out = rep(1, 6)), 

 data.frame(Name = rep("Jon", 6), 
           X = c(1,NA,3,1,NA,NA), 
           Y = c(1,1,1,2,NA,NA), 
           Z = rep(2, 6), 
         out = rep(1, 6)))

DATA <- do.call(cbind, r)  ## DATA

ar = c("out", "Name", "mdif" , "stder" , "mpre") # The names for exclusion

DATA[ , !names(DATA) %in% ar]      ## Current solution
#>
#    X  Y Z X.1 Y.1 Z.1          ## X.1 Y.1 Z.1  are automatically created but no needed
# 1  2  1 3   1   1   2
# 2  2  1 3  NA   1   2
# 3  1  1 3   3   1   2
# 4  1  2 3   1   2   2
# 5 NA  1 3  NA  NA   2
# 6 NA NA 3  NA  NA   2

【问题讨论】:

  • 创建变量是因为您将两个具有相同列名的数据框组合在一起。数据框不能有两列同名,因此 R 将 0.1 添加到每个重复项。它与您提取特定列无关。
  • 那么您的预期输出是什么?您要删除那些.1 变量还是要删除后缀?

标签: r list function loops dataframe


【解决方案1】:

理想情况下,列名应该是唯一的,但如果您想保留重复的列名,我们可以在提取后使用 sub 删除 suffixes

DATA1 <- DATA[ , !names(DATA) %in% ar] 
names(DATA1) <- sub("\\.\\d+", "", names(DATA1))

DATA1
#   X  Y Z  X  Y Z
#1  2  1 3  1  1 2
#2  2  1 3 NA  1 2
#3  1  1 3  3  1 2
#4  1  2 3  1  2 2
#5 NA  1 3 NA NA 2
#6 NA NA 3 NA NA 2

【讨论】:

    【解决方案2】:

    base R中,如果我们创建一个带有索引的对象,我们可以在以后重用它,而不是对列名做额外的操作

    i1 <- !names(DATA) %in% ar
    DATA1 <- setNames(DATA[i1], names(DATA)[i1])
    DATA1
    #   X  Y Z  X  Y Z
    #1  2  1 3  1  1 2
    #2  2  1 3 NA  1 2
    #3  1  1 3  3  1 2
    #4  1  2 3  1  2 2
    #5 NA  1 3 NA NA 2
    #6 NA NA 3 NA NA 2
    

    为了可重用性,我们可以创建一个函数

    f1 <- function(dat, vec) {
          i1 <- !names(dat) %in% vec
          setNames(dat[i1], names(dat)[i1])
     }
    f1(DATA, ar)
    

    如果数据集存储在 list 中,请使用 lapply 循环 list 并应用 f1

    lst1 <- list(DATA, DATA)
    lapply(lst1, f1, vec = ar)
    

    如果'ar'元素对于不同的list元素也不同

    arLst <- list(ar1, ar2)
    Map(f1, lst1, vec = arLst)
    

    这里,

    ar1 <- c("out", "Name")
    ar2 <- c("mdif" , "stder" , "mpre")
    

    这里还有另一个使用tidyverse的选项

    library(dplyr)
    library(stringr)
    DATA %>% 
      set_names(make.unique(names(.))) %>% 
      select(-matches(str_c(ar, collapse="|"))) %>%
      set_names(str_remove(names(.), "\\.\\d+$"))
    #   X  Y Z  X  Y Z
    #1  2  1 3  1  1 2
    #2  2  1 3 NA  1 2
    #3  1  1 3  3  1 2
    #4  1  2 3  1  2 2
    #5 NA  1 3 NA NA 2
    #6 NA NA 3 NA NA 2
    

    注意:不建议列名重复

    【讨论】:

    • 顺便问一下,Base R 中是否有任何方法可以检查输入文件是否为csv
    猜你喜欢
    • 2020-02-04
    • 1970-01-01
    • 1970-01-01
    • 2016-12-18
    • 2022-12-07
    • 2021-12-29
    • 2021-10-19
    • 1970-01-01
    • 2022-01-07
    相关资源
    最近更新 更多