ChatGPT解决这个技术问题 Extra ChatGPT

从数据框中提取特定列

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

假设我的数据框是 df,并且我想提取列 ABE,这是我能找出的唯一命令:

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

有没有更紧凑的方法来做到这一点?


J
Joshua Ulrich

您可以使用列名向量进行子集化。我非常喜欢这种方法,而不是那些将列名视为对象名(例如 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,则返回一个向量而不是数据框,这可能是不需要的:> df[,c("A")] [1] 1。使用 subset 没有这个缺点。
S
Sam Firke

如果您的 data.frame 名为 df1,则使用 dplyr 包:

library(dplyr)

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

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

select(df1, A, B, E)

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

这是 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") 是一个向量,而不是一个列表。
它将数据框转换为列表。
H
Henry

有两个明显的选择: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

s
so860

仅出于某种原因

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

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


A
Arthur Yip

其中 df1 是您的原始数据框:

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

这不使用 dplyr。它使用 base::subset,并且与 Stephane Laurent's answer 相同,只是您使用列号而不是列名。
G
Gilad Green

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

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

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


m
moodymudskipper

您可以使用 with

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

M
Mohamed Rahouma
df<- dplyr::select ( df,A,B,C)

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

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

这已经在接受的答案中
f
fxi

[ 和子集不可替代:

如果只选择一列,[ 会返回一个向量。

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]