R - 使用嵌套循环重命名多个数据帧中的多个列

时间:2017-06-05 11:44:29

标签: r loops dataframe

我有29个数据框,名为Student1到Student 29.这29个数据框中的每一个都包含变量Name,Ethnic和Membership.number,每个都有相应的数字。例如Student1包含Name.1,Ethnic.1和Membership.number.1,Student29包含Name.29等。

我试图通过剥离这些变量名末尾的数字来标准化这些。我是R的新手,但我已经整理了以下代码来尝试自动化。

for (j in 1:29) {
 for (i in 1:3) {
    oldnames = c(paste('Name', i, sep="."), paste('Nationality', i, sep="."), paste('Membership.number', i, sep="."))
    newnames = c("Name", "Nationality", "Membership.number")
    names(paste("Student",j,sep=""))[names(paste("Student",j,sep=""))==oldnames[i]]=newnames[i]
  }
}

这似乎接近于实现我想要的,并且如果我插入Student1代替粘贴(“Student”,j,sep =“”),那么它对单个数据帧应该起作用,但粘贴(“学生” “,j,sep =”“)由于”赋值目标扩展到非语言对象“,代码似乎失败了。有什么简单的我在这里做错了吗?

1 个答案:

答案 0 :(得分:0)

问题是paste()返回一个字符串,所以你的代码实际上是这样的:

names("Student1")[names("Student1")==oldnames[i]] = newnames[i]

但是,当然,字符串"Student1"与包含您的数据框的变量Student1不同,所以这不会让您走得太远。错误消息有点令人困惑,但最终意味着您正在尝试分配给无法分配的内容。

最简单的解决方案是使用函数get()assign(),它们使用字符串命名变量(如字符串"Student1"),并允许您检索和分配变量。例如,这将重命名Student1

中的一列
dfname = "Student1"
df = get(dfname)
names(df)[names(df)=="Name.1"] = "Name"
assign(dfname, df)

所以,你可以写:

for (j in 1:29) {
    oldnames = c(paste('Name', j, sep="."), 
                 paste('Nationality', j, sep="."),
                 paste('Membership.number', j, sep="."))
    newnames = c("Name", "Nationality", "Membership.number")
    dfname = paste("Student", j, sep="")
    df = get(dfname)
    for (i in 1:3) {
        names(df)[names(df) == oldnames[i]] = newnames[i]
    }
    assign(dfname, df)
}

请注意,我已将oldnames定义修改为使用j而不是i,并将仅依赖j的定义移出内循环。这里需要注意的是,这仅适用于“顶级”(即在R提示下输入)。如果你把它放在一个函数中,那么assign()变得更加棘手,因为你需要指定 where 你想要分配的变量(在顶层使用其余的全局变量,在函数内)等等。)。

此代码仍可以改进。事实证明,您对oldnames的定义可以改写为:

oldnames = paste(c("Name","Nationality","Membership.number"), j, sep=".")

这意味着您实际上可以写:

newnames = c("Name","Nationality","Membership.number")
oldnames = paste(newnames, j, sep=".")

您可以更进一步,使用函数match。此函数在其第二个参数中获取其第一个参数的每个元素的索引,并可用于同时检索oldnames向量中所有names()的位置。然后,你甚至不需要内循环:

for (j in 1:29) {
    newnames = c("Name","Nationality","Membership.number")
    oldnames = paste(newnames, j, sep=".")
    dfname = paste("Student", j, sep="")
    df = get(dfname)
    names(df)[match(oldnames, names(df))] = newnames
    assign(dfname, df)
}

使用match来查找和替换向量中的值是一种非常常见的R技术。

最后,如果数据框中没有任何其他列(所以你真的只想删除所有后缀,包括句点和所有名称末尾的一些数字),那么R中的一个常见技巧是使用sub()使用正则表达式修改名称:

for (j in 1:29) {
    newnames = c("Name","Nationality","Membership.number")
    oldnames = paste(newnames, j, sep=".")
    dfname = paste("Student", j, sep="")
    df = get(dfname)
    names(df) = sub("\\.[0-9]+$", "", names(df))
    assign(dfname, df)
}

请注意,在R中,正则表达式中的反斜杠需要加倍,因此上面的"\\."将匹配一个句点。在清理在一堆列名称上包含不需要的前缀和后缀的数据集时,我始终使用这种基于sub的技术。

快乐的R-ing!