【问题标题】:Reordering columns in data frame once again再次重新排序数据框中的列
【发布时间】:2016-09-14 17:40:34
【问题描述】:

我想重新排序我的数据框中的列,但到目前为止我发现的结果并不令人满意。

我的数据框看起来像:

cnt  <-as.factor(c("Country 1", "Country 2", "Country 3", "Country 1", "Country 2", "Country 3" ))
bnk  <-as.factor(c("bank 1", "bank 2", "bank 3", "bank 1", "bank 2", "bank 3" ))
mayData <-data.frame(age=c(10,12,13,10,11,15), Country=cnt, Bank=bnk, q10=c(1,1,1,2,2,2),q11=c(1,1,1,2,2,2), q1=c(1,1,1,2,2,2), q9=c(1,1,1,2,2,2), q6=c(1,1,1,2,2,2), year=c(1950,1960,1970,1980,1990,2000) )

   age    Country     Bank  q10 q11 q1  q9  q6  year
1   10  Country 1   bank 1  1   1   1   1   1   1950
2   12  Country 2   bank 2  1   1   1   1   1   1960
3   13  Country 3   bank 3  1   1   1   1   1   1970
4   10  Country 1   bank 1  2   2   2   2   2   1980
5   11  Country 2   bank 2  2   2   2   2   2   1990
6   15  Country 3   bank 3  2   2   2   2   2   2000

但我想重新排列列,如下所示:

      Country     Bank  year    age q1  q6  q9  q10 q11
1   Country 1   bank 1  1950    10  1   1   1   1   1
2   Country 2   bank 2  1960    12  1   1   1   1   1
3   Country 3   bank 3  1970    13  1   1   1   1   1
4   Country 1   bank 1  1980    10  2   2   2   2   2
5   Country 2   bank 2  1990    11  2   2   2   2   2
6   Country 3   bank 3  2000    15  2   2   2   2   2

我的真实数据框有很多列,因此使用索引或每列的名称“手动”重新排列列顺序并不是最佳选择。

还要注意,对于以qs 开头的列名,我希望它们按升序排列,即从q1q11。问题是 R 无法理解 q6(代表“问题 6”)应该在 q10 之前。要查看此缺陷,请查看以下示例:

mayData<-mayData[,order(colnames(mayData),decreasing=F)] 

    age   Bank    Country   q1  q10 q11 q6  q9  year
1   10  bank 1  Country 1   1   1   1   1   1   1950
2   12  bank 2  Country 2   1   1   1   1   1   1960
3   13  bank 3  Country 3   1   1   1   1   1   1970
4   10  bank 1  Country 1   2   2   2   2   2   1980
5   11  bank 2  Country 2   2   2   2   2   2   1990
6   15  bank 3  Country 3   2   2   2   2   2   2000

因此,基本上我想要重新排序列的方式是首先根据我的偏好以某种灵活的方式对几列进行排序,然后使用递减的排序标准。但是,“合乎逻辑”的一个,R 可以理解以正确排序 qs 的一个。

【问题讨论】:

  • 改用q01q06q09
  • 您可以根据as.numeric(sub("^q", "", colnames(...))) 订购您的q.. 列(并且您可以使用grep("^q", colnames(mayData)) 之类的内容发现这些列)

标签: r data-manipulation data-cleaning


【解决方案1】:

我们可以使用gtools 中的mixedsort 来排列“q”列。

library(gtools)
i1 <- grep("q\\d+", names(mayData))
nm1 <- mixedsort(names(mayData)[i1])
mayData[c(setdiff(names(mayData), nm1), nm1)]
#  age   Country   Bank year q1 q6 q9 q10 q11
#1  10 Country 1 bank 1 1950  1  1  1   1   1
#2  12 Country 2 bank 2 1960  1  1  1   1   1
#3  13 Country 3 bank 3 1970  1  1  1   1   1
#4  10 Country 1 bank 1 1980  2  2  2   2   2
#5  11 Country 2 bank 2 1990  2  2  2   2   2
#6  15 Country 3 bank 3 2000  2  2  2   2   2

注意:仅使用 base R 函数和单个包。

或者正如@Cath 提到的,删除带有gsub 的子字符串也可以用于订购

sort(as.numeric(sub("^q", "", names(mayData)[i1])))

【讨论】:

  • 你甚至可以避免使用sort(as.numeric(sub("^q", "", names(mayData)[i1]))) 加载gtools ;-)
  • 谢谢,但是排序不完整,因为它错过了我想要重新排列其他列的方式。除非您没有其他有趣的建议,否则我相信我可以结合此处的其他回复自行处理。
  • @msh855 这是您在帖子中显示的预期输出。其他列Country Bank year age 不按字母顺序排列。所以,我不确定你想订购什么样的图案
【解决方案2】:

您可以使用单个数字重命名列名称以添加前导零:

cn <- names(mayData)
q_digit <- cn[grep("^q[0-9]$", cn)]
names(mayData)[names(mayData) %in% q_digit] <- gsub("q", "q0", q_digit)
mayData[,order(colnames(mayData),decreasing=F)] 

mayData    
age   Bank   Country   q01 q06 q09 q10 q11 year
1  10 bank 1 Country 1   1   1   1   1   1 1950
2  12 bank 2 Country 2   1   1   1   1   1 1960
3  13 bank 3 Country 3   1   1   1   1   1 1970
4  10 bank 1 Country 1   2   2   2   2   2 1980
5  11 bank 2 Country 2   2   2   2   2   2 1990
6  15 bank 3 Country 3   2   2   2   2   2 2000

这假设您的问题少于 100 个,如果您有更多问题,您可以调整它以在两位数列名称中添加另一个零。

【讨论】:

  • 谢谢,这可能会解决 q 的排序问题,但我可以如何组合以重新排列其他列,例如最终获得我可以在我的问题中获得的第二个表。在这一步之后,你建议这个“手动”吗?
  • 哦,我的错,我没有看到这部分。看看 alistaire 的答案,它比我的要好得多,并且涵盖了这一点。
【解决方案3】:

利用dplyrselectnum_rangetidyr::extract_numeric

library(dplyr)
library(tidyr)

mayData %>% select(Country, Bank, year, age, 
                   num_range('q', sort(extract_numeric(names(mayData)))))
#     Country   Bank year age q1 q6 q9 q10 q11
# 1 Country 1 bank 1 1950  10  1  1  1   1   1
# 2 Country 2 bank 2 1960  12  1  1  1   1   1
# 3 Country 3 bank 3 1970  13  1  1  1   1   1
# 4 Country 1 bank 1 1980  10  2  2  2   2   2
# 5 Country 2 bank 2 1990  11  2  2  2   2   2
# 6 Country 3 bank 3 2000  15  2  2  2   2   2

【讨论】:

    猜你喜欢
    • 2020-02-24
    • 1970-01-01
    • 2014-06-19
    • 2019-02-12
    • 1970-01-01
    • 2013-08-22
    • 2019-01-23
    • 2019-12-20
    • 2023-03-16
    相关资源
    最近更新 更多