在一个数据框中按升序重新排列指定的列。

3
我有一个简短的问题,如何仅按选定的列名重新排序数据框。我需要一个通用的解决方案,因为我必须在不同数量的V列上使用它(每次都有V列>100)。
例如:
假设我有以下数据:
dkk <- structure(list(A = 2L, X = 3L, C = 4L, D = 5L, Z = 6L, V1 = 5L, 
                     V6 = 5L, V4 = 5L, V5 = 5L, V3 = 2L, V2 = 2L), .Names = c("X", 
                                                                              "B", "C", "D", "Z", "V1", "V6", "V4", "V5", "V3", "V2"), 
                class = "data.frame", row.names = c(NA, -1L)) 

# X B C D Z V1 V6 V4 V5 V3 V2
  2 3 4 5 6  5  5  5  5  2  2

我该如何使用V字形重新排序列,以使它们按升序排列?
# X B C D Z V1 V2 V3 V4 V5 V6
  2 3 4 5 6  5  2  2  5  5  5

非常感谢!
2个回答

4

使用中的setcolorder会更快。

library(data.table)
i1 <- grep("V\\d+", names(dkk), value = TRUE)
cbind(dkk[setdiff(names(dkk), i1)], setcolorder(dkk[i1], order(i1))[])
#  A B C D Z V1 V2 V3 V4 V5 V6
#1 2 3 4 5 6  5  2  2  5  5  5

当“V”名称与其他列混合在一起时,情况会变得有些复杂。例如,假设我们将列名称更改为

set.seed(24)
names(dkk) <- sample(names(dkk))
dkk
#   D C V6 Z V4 V1 B V2 V3 A V5
#1 2 3  4 5  6  5 5  5  5 2  2

现在的选择是创建一个包含“V”(“i2”)的列的数字索引,提取名称(“i3”),然后分别分配名称和列的顺序。
i2 <- grep("^V\\d+", names(dkk))
i3 <- names(dkk)[i2]
names(dkk)[i2] <- sort(names(dkk)[i2])
dkk[i2] <- dkk[i2][order(i3)]

获取

dkk
#  D C V1 Z V2 V3 B V4 V5 A V6
#1 2 3  5 5  5  5 5  6  2 2  4

更新

上述解决方案存在一个小问题。当我们的列名包含大于9的数字时,即“V10”,“V11”等,sort不会正确排序。假设我们的第三个列名为“V100”。

colnames(dkk)[3] <- "V100"   
dkk
#  D C V100 Z V4 V1 B V2 V3 A V5
#1 2 3    4 5  6  5 5  5  5 2  2

i2 <- grep("^V\\d+", names(dkk))
i3 <- names(dkk)[i2]

我们可以使用 parse_number 来解析数字部分,以帮助排序。
i4 <- readr::parse_number(i3)
names(dkk)[i2] <- i3[order(i4)]
dkk[i2] <- dkk[i2][order(i4)]
dkk
#  D C V1 Z V2 V3 B V4 V5 A V100
#1 2 3  5 5  5  5 5  6  2 2    4

数据

dkk <- structure(list(A = 2L, B = 3L, C = 4L, D = 5L, E = 6L, V1 = 5L,
                 V6 = 5L, V4 = 5L, V5 = 5L, V3 = 2L, V2 = 2L), .Names = c("A",
                                                                          "B", "C", "D", "Z", "V1", "V6", "V4", "V5", "V3", "V2"),
            class = "data.frame", row.names = c(NA, -1L))

2
你可以使用 order 对列名进行排序:
dkk[,order(colnames(dkk))]

  A B C D E V1 V2 V3 V4 V5 V6
  2 3 4 5 6  5  2  2  5  5  5

编辑:仅按包含“V”的列排序。注意:数据集中包括一个Z列。基本上,我将不需要排序的列名称与需要排序的“V”列进行了区分。

dkk <- structure(list(A = 2L, B = 3L, C = 4L, D = 5L, E = 6L, V1 = 5L,
                     V6 = 5L, V4 = 5L, V5 = 5L, V3 = 2L, V2 = 2L), .Names = c("A",
                                                                              "B", "C", "D", "Z", "V1", "V6", "V4", "V5", "V3", "V2"),
                class = "data.frame", row.names = c(NA, -1L))

cols <- c(colnames(dkk)[!grepl("V",names(dkk))],
colnames(dkk)[grepl("V",names(dkk))][order(colnames(dkk)[grepl("V",names(dkk))])])

dkk[,cols]

  A B C D Z V1 V2 V3 V4 V5 V6
1 2 3 4 5 6  5  2  2  5  5  5

谢谢,当我有这些名称(A、B、C、D、E、V1:Vend)时,这个程序可以正常工作,但是如果我有这些名称(A、X、C、D、Z、V1:Vend),那么该怎么办呢?因为这会使得X和Z排在所有的V之后。 - JmO

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接