在R中对列排序:先字符串(按字母顺序),然后数字(按数字顺序)

bvjveswy  于 2023-10-13  发布在  其他
关注(0)|答案(4)|浏览(204)

我在R中有一个由字母和数字组成的列(例如。“A”、“B”、“1”、“2”等)。我想排序的点阵在这样一种方式,我有字母第一(按字母排序)其次是数字(按数字排序)。理想情况下,以一种整齐的方式,但不一定。
gtools::mixedsort几乎做到了我想要的,但是把数字放在字符串之前,我不认为有一个参数允许你把数字推到后面。
我考虑过拆分这个框架,分别对每个框架进行排序,然后再次按行绑定。但我猜应该有更好的方法来做到这一点?
这里也有一个例子来进一步澄清我的问题。
我有:

Col1    Col2   Col3
Apples     A     90
Pears     12     90
Bananas    C     50
Cake       1     50
Apples     A     90
Pears      B     90
Bananas    2     50
Cake     100     50

我试图实现的是按Col 2排序,首先按几何排序,然后按数字排序:

Col1    Col2   Col3
Apples     A     90
Apples     A     90
Apples     A     90
Apples     A     90
Pears      B     90
Bananas    C     50
Cake       1     50
Bananas    2     50
Pears     12     90
Cake     100     50

多谢了!

6xfqseft

6xfqseft1#

对于基本R选项:

df <- data.frame(Col2=c("100", "B", "A", "Z", "10", "4"), stringsAsFactors=FALSE)
df[order(grepl("^\\d+$", df$Col2), sprintf("%10s", df$Col2)), ]

[1] "A"   "B"   "Z"   "4"   "10"  "100"

这里的两个排序级别首先将字母放在数字之前。第二个排序级别将所有字符填充为10个带0的字符。然后它会上升。这实际上是数字的升序数字排序。这里的技巧是要认识到,如果数字字符串都具有相同的宽度,那么它们实际上可以像文本一样正确排序。

ssgvzors

ssgvzors2#

也许不是最佳解决方案,但使用dplyr并将您提供的数据称为df

numbers <- df %>% 
  filter(!(Col2 %in% LETTERS)) %>% 
  mutate(Col2 = as.numeric(Col2)) %>% 
  arrange(Col2) %>% 
  mutate(Col2 = as.character(Col2))

non_numbers <- df %>% 
  filter(Col2 %in% LETTERS) %>% 
  arrange(Col2)

output <- rbind(non_numbers, numbers)

输出量:

Col1 Col2 Col3
1  Apples    A   90
2  Apples    A   90
3   Pears    B   90
4 Bananas    C   50
5    Cake    1   50
6 Bananas    2   50
7   Pears   12   90
8    Cake  100   50
mefy6pfw

mefy6pfw3#

不是按照你想要的顺序。但行绑定可以解决这个问题。

DT <- fread("Col1    Col2   Col3
Apples     A     90
Pears     12     90
Bananas    C     50
Cake       1     50
Apples     A     90
Pears      B     90
Bananas    2     50
Cake     100     50")

library(gtools)
DT[mixedorder(DT$Col2),]
qnakjoqk

qnakjoqk4#

您可以使用as.numeric将字符串数字转换为数字。由于有一些字符,你会收到来自as.numeric的警告,我使用suppressWarnings抑制了这些字符。使用这个数字和order中的字符串对向量进行排序。此外,可以选择radix排序,这可以提高速度。

s <- c(-1, -10, 2.5, "1e2", "A", 12, "C", 1, "A", "B", 2, 100)

s[order(suppressWarnings(as.numeric(s)), s, na.last = FALSE)]
#s[order(suppressWarnings(as.numeric(s)), s, na.last = FALSE, method="radix")] #Alternative
# [1] "A"   "A"   "B"   "C"   "-10" "-1"  "1"   "2"   "2.5" "12"  "100" "1e2"

相关问题