【问题标题】:Extracting specific columns from a data frame从数据框中提取特定列
【发布时间】:2012-04-22 13:40:18
【问题描述】:

我有一个包含 6 列的 R 数据框,我想创建一个只有三列的新数据框。

假设我的数据框是df,我想提取列ABE,这是我能弄清楚的唯一命令:

 data.frame(df$A,df$B,df$E)

有没有更简洁的方法?

【问题讨论】:

    标签: r dataframe r-faq


    【解决方案1】:

    您可以使用列名向量进行子集化。我非常喜欢这种方法,而不是那些将列名视为对象名的方法(例如subset()),尤其是在函数、包或应用程序中编程时。

    # data for reproducible example
    # (and to avoid confusion from trying to subset `stats::df`)
    df <- setNames(data.frame(as.list(1:5)), LETTERS[1:5])
    # subset
    df[c("A","B","E")]
    

    注意没有逗号(即不是df[,c("A","B","C")])。那是因为df[,"A"] 返回一个向量,而不是一个数据框。但是df["A"] 总会返回一个数据框。

    str(df["A"])
    ## 'data.frame':    1 obs. of  1 variable:
    ## $ A: int 1
    str(df[,"A"])  # vector
    ##  int 1
    

    感谢David Dorchies 指出df[,"A"] 返回一个向量而不是data.frame,并感谢Antoine Fabri 为我的原始解决方案(下)提出更好的替代方案(上)。

    # subset (original solution--not recommended)
    df[,c("A","B","E")]  # returns a data.frame
    df[,"A"]             # returns a vector
    

    【讨论】:

    • 这给出了错误object of type 'closure' is not subsettable
    • @ArenCambre:那么你的 data.frame 并没有真正命名为 dfdf也是stats包中的一个函数。
    • @Cina:因为-"A" 是语法错误。而?Extract 说,“ij... 也可以是负整数,表示要从选择中忽略的元素/切片。”
    • 这种语法存在问题,因为如果我们只提取一列 R,则返回一个向量而不是数据帧,这可能是不需要的:&gt; df[,c("A")][1] 1。使用subset 没有这个缺点。
    【解决方案2】:

    有两个明显的选择:Joshua Ulrich 的df[,c("A","B","E")]

    df[,c(1,2,5)]
    

    > df <- data.frame(A=c(1,2),B=c(3,4),C=c(5,6),D=c(7,7),E=c(8,8),F=c(9,9)) 
    > df
      A B C D E F
    1 1 3 5 7 8 9
    2 2 4 6 7 8 9
    > df[,c(1,2,5)]
      A B E
    1 1 3 8
    2 2 4 8
    > df[,c("A","B","E")]
      A B E
    1 1 3 8
    2 2 4 8
    

    【讨论】:

      【解决方案3】:

      这是subset()函数的作用:

      > dat <- data.frame(A=c(1,2),B=c(3,4),C=c(5,6),D=c(7,7),E=c(8,8),F=c(9,9)) 
      > subset(dat, select=c("A", "B"))
        A B
      1 1 3
      2 2 4
      

      【讨论】:

      • 当我用我的数据尝试这个时,我得到了错误:“ x[j] 中的错误:无效的下标类型 'list'” 但是如果 c("A", "B") 是不是列表,是什么?
      • @Rafael_Espericueta 如果不查看您的代码,很难猜到...但是c("A", "B") 是一个向量,而不是一个列表。
      • 它将数据框转换为列表。
      【解决方案4】:

      使用dplyr 包,如果你的data.frame 被称为df1

      library(dplyr)
      
      df1 %>%
        select(A, B, E)
      

      这也可以在没有%&gt;% 管道的情况下写成:

      select(df1, A, B, E)
      

      【讨论】:

      • 鉴于自发布我的问题以来 Tidyverse 的巨大发展,我已将答案转给您。
      • 鉴于 tidyverse 的剧烈变化速度,我会告诫不要使用这种模式。这是我强烈反对在为函数、包或应用程序编写代码时将列名视为对象名的强烈偏好。
      • 这个答案提交已经四年多了,模式没有改变。管道表达式可以非常直观,这就是它们吸引人的原因。
      • 您可以将管道链接在一起,例如:df1 %&gt;% select(A, B, E) %&gt;% rowMeans(.)。通过键入?magrittr::`%&gt;%` 查看%&gt;% 管道的文档
      • 这是一个有用的解决方案,但对于问题中给出的示例,Josh 的答案更具可读性、更快且无依赖性。我希望新用户在深入研究 tidyverse 之前学习方括号子集 :)!
      【解决方案5】:

      df1 是您的原始数据框:

      df2 <- subset(df1, select = c(1, 2, 5))
      

      【讨论】:

      【解决方案6】:

      [ 和子集不可替代:

      [ 确实会在仅选择一列时返回一个向量。

      df = data.frame(a="a",b="b")    
      
      identical(
        df[,c("a")], 
        subset(df,select="a")
      ) 
      
      identical(
        df[,c("a","b")],  
        subset(df,select=c("a","b"))
      )
      

      【讨论】:

      • 如果您设置了drop=FALSE,则不会。示例:df[,c("a"),drop=F]
      【解决方案7】:

      您还可以使用sqldf 包对 R 数据帧执行选择:

      df1 <- sqldf("select A, B, E from df")
      

      这给出了一个数据框df1 的输出,其列:A、B、E。

      【讨论】:

        【解决方案8】:

        只是出于某种原因

        df[, (names(df) %in% c("A","B","E"))]
        

        为我工作。上述所有语法都产生了“未定义的列选择”。

        【讨论】:

          【解决方案9】:

          你可以使用with

          with(df, data.frame(A, B, E))
          

          【讨论】:

            【解决方案10】:
            df<- dplyr::select ( df,A,B,C)
            

            此外,您可以为新创建的数据分配不同的名称

            data<- dplyr::select ( df,A,B,C)
            

            【讨论】:

            • 这已经在接受的答案中
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-10-24
            • 1970-01-01
            • 2017-03-01
            • 1970-01-01
            相关资源
            最近更新 更多