是否可以将具有多个小数点的数字视为数字以检查列中存在的字母字符并在 R 中对列进行排序?

Is it possible to treat numbers with multiple decimal points as numeric to check for letter characters present in column and sort column in R?

我有一个数据框,其中一列的数字混合了整数、数字和多个小数点(例如 3、1.1、1.2.1、1.2.2.3)。我有两个问题:

  1. 我如何检查以确保列中只使用了数字(即不存在任何字符)?如果存在字符,那么是哪几行?
  2. 在 R 中是否有一种方法可以将它们视为数字以便对列进行排序?

最小示例

数据

library(dplyr)

df <-
  structure(list(
    index = 1:15,
    section = c("2.1.1", "2.1.1", "2.1.2.4", "2.1.3", "2.1.2.9", "2.1.4", 
                "2.1.4", "2.1.4", "3", "3", "4", "1.1", "1.5", "1.5", "b.1")),
  class = "data.frame",
  row.names = c(NA,-15L))

我试过的

如果我尝试将列设为数字,那么它会将具有多个小数点的数字强制转换为 NA

> as.numeric(df$section)
 [1]  NA  NA  NA  NA  NA  NA  NA  NA 3.0 3.0 4.0 1.1 1.5 1.5

Warning message: NAs introduced by coercion

然后,为了测试列中的字符,我知道如果我只有整数或常规数值,我可以这样做来测试哪些行有字符(不包括 NA):

# Check for which (if any) rows have NAs.
na.index <- which(is.na(df$section))

# Find any rows that are character, excluding NAs (hence the setdiff).
index <- which(is.na(as.numeric(as.character(df$section)))) %>%
  setdiff(na.index)

# Output
index

[1]  1  2  3  4  5  6  7  8 15

在这里,它将任何具有多个小数位的数字视为字符(以及带有字母的数字)。所以,我希望能够将多个十进制数视为数字,然后将 b.1 标记为字符。我可以创建一个新的专栏来区分这些。

对于排序,似乎 base sort 会正确排列它们,但不确定这是否一直有效。

sort(df$section)

#Output
[1] "1.1"     "1.5"     "1.5"     "2.1.1"   "2.1.1"   "2.1.2.4" "2.1.2.9" "2.1.3"   
"2.1.4"   "2.1.4"   "2.1.4"   "3"       "3"       "4"       "b.1" 

这是我的预期输出(考虑到字母字符的排序和检查)。排序时,如果section numbers相同,则可以按索引列排序(数值小的先排)。

预期输出

   index section      type
1     12     1.1   numeric
2     13     1.5   numeric
3     14     1.5   numeric
4      1   2.1.1   numeric
5      2   2.1.1   numeric
6      3 2.1.2.4   numeric
7      5 2.1.2.9   numeric
8      4   2.1.3   numeric
9      6   2.1.4   numeric
10     7   2.1.4   numeric
11     8   2.1.4   numeric
12     9       3   numeric
13    10       3   numeric
14    11       4   numeric
15    15     b.1 character

我在 Java (here) 等其他语言中看到过一些关于 SO 的讨论,但不确定如何在 R 中处理它,尤其是因为每行。

我们可以使用 str_detect 检查仅数字元素,并且 arrange 基于对 'section' 与 mixedsort

的排序
library(dplyr)
library(stringr)
df %>% 
    mutate(type = c("character", "numeric")[1 +
        str_detect(section, "^[0-9.]+$")])%>%
    arrange(match(section, gtools::mixedsort(section)))

-输出

index section      type
1     12     1.1   numeric
2     13     1.5   numeric
3     14     1.5   numeric
4      1   2.1.1   numeric
5      2   2.1.1   numeric
6      3 2.1.2.4   numeric
7      5 2.1.2.9   numeric
8      4   2.1.3   numeric
9      6   2.1.4   numeric
10     7   2.1.4   numeric
11     8   2.1.4   numeric
12     9       3   numeric
13    10       3   numeric
14    11       4   numeric
15    15     b.1 character

我们可以使用str_detect来检查字符串中是否有字母。要对列进行排序,请使用 arrange:

library(dplyr)
library(stringr)
df %>% 
    mutate(test = str_detect(section, "[a-zA-Z]")) %>% 
    arrange(section)

输出:

  index section  test
1     12     1.1 FALSE
2     13     1.5 FALSE
3     14     1.5 FALSE
4      1   2.1.1 FALSE
5      2   2.1.1 FALSE
6      3 2.1.2.4 FALSE
7      5 2.1.2.9 FALSE
8      4   2.1.3 FALSE
9      6   2.1.4 FALSE
10     7   2.1.4 FALSE
11     8   2.1.4 FALSE
12     9       3 FALSE
13    10       3 FALSE
14    11       4 FALSE
15    15     b.1  TRUE