从R data.frame中选择一组变量名称的最有效方法是什么?

时间:2012-02-24 04:00:19

标签: r

问题:

我经常需要从R中的data.frame中选择一组变量。 我的研究是在社会和行为科学中,拥有一个包含数百个变量的数据框架是很常见的(例如,一系列调查问题,人口统计项目,绩效指标等都有项目级信息。 。等。)。

作为分析的一部分,我经常想要选择变量的子集。 例如,我可能想要:

  • 一组变量的描述性统计
  • 一组变量的相关矩阵
  • 对一组变量的因子分析
  • 线性模型中的预测变量

现在,我知道有很多方法可以编写代码来选择变量的子集。 Quick-r has a nice overview of common ways of extracting variable subsets from a data.frame

例如,

myvars <- c("v1", "v2", "v3")
newdata <- mydata[myvars]

但是,我对此过程的效率感兴趣,特别是在您可能需要从data.frame中提取20个左右的变量时。变量的命名约定通常不直观,特别是在您从其他人继承数据集的情况下,因此您可能会感到疑惑,变量GendergendersexGENDERgender1等 将此乘以需要提取的20个变量,记忆变量名称的任务变得比它需要的更复杂。

具体示例

为了使以下讨论具体,我将使用bfi包中的psych data.frame。

library(psych)
data(bfi)
df <- bfi
head(df, 1)
      A1 A2 A3 A4 A5 C1 C2 C3 C4 C5 E1 E2 E3 E4 E5 N1 N2 N3 N4 N5 O1 O2 O3 O4
61617  2  4  3  4  4  2  3  3  4  4  3  3  3  4  4  3  4  2  2  3  3  6  3  4
      O5 gender education age
61617  3      1        NA  16
  • 如何有效地选择一组任意变量,具体而言,我会选择A1, A2, A3, A5, C2, C3, C5, E2, E3, gender, education, age

我目前的策略

我目前使用的是一系列策略。 当然,有时我可以利用变量的数字位置或命名约定之类的东西,并使用grep来选择或paste来构造。但有时我需要一个更通用的解决方案。我一直使用以下内容:

1。名(DF)

在早期,我曾经打电话给names(df),复制引用的变量名,然后编辑,直到我得到我想要的。

2。使用数据库

有时候我会有一个单独的data.frame,它将每个变量存储为一行,并且包含变量名称,变量标签的列,并且它有一个列,指示是否应该为特定分析保留变量。然后,我可以过滤该include变量并提取变量名称的向量。我发现这在我开展心理测试和各种迭代时特别有用,我希望包含或排除某些项目。

3。 dput(名(DF))

由于Hadley Wickham once pointed out to me dput是一个不错的选择;例如,dput(names(df))优于names(df),因为它会输出已经采用c("var1", "var2", ...)格式的列表:

dput(names(df))
c("A1", "A2", "A3", "A4", "A5", "C1", "C2", "C3", "C4", "C5", 
"E1", "E2", "E3", "E4", "E5", "N1", "N2", "N3", "N4", "N5", "O1", 
"O2", "O3", "O4", "O5", "gender", "education", "age")

然后可以将其复制到脚本中并进行编辑。

但它可以更有效率

我猜dput是一个非常好的变量选择策略。这个过程的效率在很大程度上取决于你将文本复制到脚本中的能力,然后将名称列表编辑到所需的名称。

但是,我仍然记得基于GUI的变量选择系统的效率。 例如,在SPSS中,当您与对话框进行交互时,您可以使用鼠标指向并单击所需的数据集中的变量。您可以按住Shift键单击以选择一系列变量,您可以按住shift并按向下键选择一个或多个变量,依此类推。然后,您可以按Paste,并将带有解压缩变量名称的命令粘贴到脚本编辑器中。

所以,最后是核心问题

  • 是否有一个简单的没有多余的GUI设备允许从data.frame中选择变量(例如像guiselect(df)这样的东西打开一个用于变量选择的gui窗口),并返回一个选择的变量名称向量{ {1}}?
  • c("var1", "var2", ...)是在R中选择一组变量名的最佳选择吗?或者有更好的方法吗?

更新(2017年4月):我已经发布了自己对good strategy below的理解。

5 个答案:

答案 0 :(得分:23)

我个人是myvars <- c(...)的粉丝,然后从那里使用mydf[,myvars]

然而,这仍然需要您输入初始变量名称(即使只是一次),并且就我读到您的问题而言,正是您要问的是这个初始的“选择变量名称”。

一个简单的简单的GUI设备 - 我最近被介绍到menu函数,这是一个简单的简单的GUI设备,用于选择一个对象一系列选择。尝试menu(names(df),graphics=TRUE)查看我的意思(返回列号)。如果由于某种原因你的系统无法处理图形,它甚至可以提供一个很好的文本界面(尝试使用graphics=FALSE看看我的意思。)

然而,这对您的用途有限,因为您只能选择一个列名。 要选择多个,您可以使用select.list(在?menu中提及作为进行多项选择的替代方法):

# example with iris data (I don't have 'psych' package):
vars <- select.list(names(iris),multiple=TRUE,
                    title='select your variable names',
                    graphics=TRUE)

这也需要graphics=TRUE选项(单击要选择的所有项目)。 它返回变量的名称。

答案 1 :(得分:10)

您可以使用select.list(),如下所示:

DF <- data.frame(replicate(26,list(rnorm(5))))
names(DF) <- LETTERS
subDF <- DF[select.list(names(DF), multiple=TRUE)]

答案 2 :(得分:5)

我使用以下策略在R效率中进行变量选择。

使用元数据存储变量名称

对于某些变量集,我有每个变量一行的数据框。例如,我可能会进行100项个性测试。元数据包括R中的变量名称以及所有评分信息(例如,项目是否应该反转等等)。然后,我可以从此元数据中提取项目和比例名称的变量名称。

将变量集存储在命名列表

在每个项目中,我都有一个名为v的列表,用于存储命名的变量集。 然后在任何需要一组变量的分析中,我只能引用命名列表。这也使代码更可靠,因为如果变量名称发生变化,那么所有的偶然分析都会发生变化。它还有助于在变量的排序方式中创建一致性。

这是一个简单的例子:

v <- list()
v$neo_items <- meta.neo$id
v$ds14_items <- meta.ds14$id
v$core_items <- c(v$neo_items, v$ds14_items)       

v$typed_scales <- c("na", "si")
v$typed_all <- c("typed_continuous_sum", "na", "si")
v$neo_facets <- sort(unique(meta.neo$facet))
v$neo_factors <- c("agreeableness", "conscientiousness", 
                   "extraversion", "neuroticism", "openness")
v$outcomes_scales <- c("healthbehavior", "socialsupport", 
                "physical_symptoms", "psychological_symptoms")

从上面的例子可以看出几点:

  • 通常,变量列表将从我单独存储的元数据生成。例如,我有meta.neo$id
  • 中存储的neo个性测试的240个字符的变量名称
  • 在某些情况下,可以从元数据派生变量名称。例如,我的人格测试元数据中的一列显示了该项所属的比例,并且通过获取该列的unique值来从该列派生变量名称。
  • 在某些情况下,变量集是较小集合的组合。因此,例如,您可能有一组用于预测变量,一组用于结果,一组用于组合预测变量和结果。对预测变量和结果的划分可能对某些回归模型有用,并且组合集可能对相关矩阵或因子分析有用。
  • 对于更多临时变量列表,我仍然使用dput(names(df) df是我的data.frame来生成字符名称的向量,然后存储在变量列表中。
  • 这些变量列表通常在您加载数据后放置,但在您进行操作之前。这样,它们可用于数据准备,当您开始运行分析时(例如,预测模型,相关性,描述性统计等),它们当然可用。
  • 变量列表的美妙之处在于您可以在RStudio中轻松使用auto-copmlete。因此,您不需要记住变量名称甚至变量列表的名称。您只需输入v$,然后按Tab键或v$以及列表名称的某些部分。

使用变量列表

使用变量列表非常简单,但R中的某些函数以不同的方式指定变量名称。

简单和标准方案涉及向data.frame子集提供变量名称列表。例如,

cor(data[,v$mylist])
cor(data[,v$predictors], data[,v$outcomes])

对于需要公式的函数来说,这有点棘手。您可能需要编写一个函数。例如:

v <- list()
v$predictors <- c("cyl", "disp")
f <- as.formula(paste("mpg ~", paste(v$predictors, collapse = " + ")))
lm(f, mtcars)

您还可以在sapplylapply等函数中使用变量列表(可能是tidyverse等价物)。例如,

使用以下命令创建描述性统计表:

sapply(mydata[, v$outcomes], function(X) c(mean = mean(X), sd = sd(X)))

dput仍然有用

对于即席变量,或者即使您只是编写代码来创建变量列表,dput仍然非常有用。

标准代码为dput(names(df)),其中df是您的data.frame。例如:

 dput(names(mtcars))

可生产

 c("mpg", "cyl", "disp", "hp", "drat", "wt", "qsec", "vs", "am", 
 "gear", "carb")

然后,您可以编辑此字符串以提取所需的变量。 这样做的另一个好处是可以减少代码中的输入错误。这是非常重要的一点。您不想花费大量时间尝试调试仅仅是错字导致的代码。此外,错误输入变量名称时的Rs错误消息很糟糕。它只是说&#34;选择了未定义的列&#34;。它没有告诉你哪些变量名称是错误的。

如果您有大量变量,您还可以使用一系列字符串搜索功能来提取变量名称的子集:

例如

> library(psych)
> dput(names(bfi)) #all items
c("A1", "A2", "A3", "A4", "A5", "C1", "C2", "C3", "C4", "C5", 
"E1", "E2", "E3", "E4", "E5", "N1", "N2", "N3", "N4", "N5", "O1", 
"O2", "O3", "O4", "O5", "gender", "education", "age")
> dput(grep("^..$", names(bfi), value = TRUE)) # two letter variable names
c("A1", "A2", "A3", "A4", "A5", "C1", "C2", "C3", "C4", "C5", 
"E1", "E2", "E3", "E4", "E5", "N1", "N2", "N3", "N4", "N5", "O1", 
"O2", "O3", "O4", "O5")
> dput(grep("^E.$", names(bfi), value = TRUE)) # E items
c("E1", "E2", "E3", "E4", "E5")
> dput(grep(".5$", names(bfi), value = TRUE)) # 5th items
c("A5", "C5", "E5", "N5", "O5")

清理现有变量名称并使用命名约定

当我从其他人那里获得数据文件时,变量名称通常缺少约定或使用约定,这使得在R中使用的变量不太有用。我使用的一些规则:

  • 使所有变量都小写(不得不考虑大小写变量只是讨厌)
  • 使变量名具有内在意义(其他一些软件使用变量标签来存储有意义的数据; R并不真正使用标签)
  • 将变量保持适当的长度(即不要太长)。最多10个字符。超过20令人讨厌。

所有这些步骤通常使变量选择更容易,因为要记住的不一致性更少。

使用单个变量名称的选项卡完成

对于个别变量,我通常使用数据框中的自动完成功能。例如,df$并按下标签。

我尝试使用允许我尽可能使用自动完成的编码风格。我不喜欢要求我在不使用自动完成的情况下知道变量名称的函数。例如,在对data.frame进行子集化时,我更喜欢

df[ df$sample == "control", ]

subset(df, sample == "control")

因为我可以自动填写变量名称&#34; sample&#34;在顶部示例中,但不在第二个示例中。

答案 3 :(得分:3)

如果你想要一个忽略变量的方法并且可能根据它们的'stems'选出变量的方法,那么使用适当的正则表达式模式和ignore.case- = TRUE和value = TRUE with grep:

 dfrm <- data.frame(var1=1, var2=2, var3=3, THIS=4, Dont=5, NOTthis=6, WANTthis=7)
unlist(sapply( c("Want", "these", "var"),
   function(x) grep(paste("^", x,sep=""), names(dfrm), ignore.case=TRUE, value=TRUE) ))
#----------------
      Want       var1       var2       var3   # Names of the vector
"WANTthis"     "var1"     "var2"     "var3"   # Values matched
> dfrm[desired]
  WANTthis var1 var2 var3
1        7    1    2    3

答案 4 :(得分:0)

您的意思是select吗?

sub_df = subset(df, select=c("v1","v2","v3"))