R:在数据帧单元中对数据进行排序
我有多个列的巨大数据框,其中一列包含这样的数据R:在数据帧单元中对数据进行排序,r,regex,dataframe,R,Regex,Dataframe,我有多个列的巨大数据框,其中一列包含这样的数据 No "48.8.1.1." "48.8.1.2." "48.8.2." "48.9." "48.10." "48.11." "48.11.1." "48.11.1.1." "48.11.1.2
No
"48.8.1.1."
"48.8.1.2."
"48.8.2."
"48.9."
"48.10."
"48.11."
"48.11.1."
"48.11.1.1."
"48.11.1.2."
"48.11.1.2.2.2.2.1."
数据的子顺序中没有固定的顺序
问题:
df$No<-substring(df$No,1,9)
而不是
"48.11.1.2.1."
某些值的顺序不正确,如ex:
"48.11.1.2.2.2.2.1"
2号是额外的。
如何删除2的额外数字
我确实尝试过一些方法,比如重置索引等,但都不起作用。
需要一些建议。试试:
编辑::
df$No<-stringr::str_remove_all(df$No,"2.{1,}(?=2.{3,})")
原件::
df$No<-substring(df$No,1,9)
数据:
df假设字符串序列表示大纲中各部分的编号,以下是一种可能的解决方案:
library(data.table)
# reshape to long format
long <- DT[, rn := .I][
, strsplit(No, "[.]"), by = rn][
, V1 := as.integer(V1)][
, lvl := rowid(rn)][]
# find contiguous streaks of rows where there is a gap in levels
nlvl <- long[, .N, keyby = rn][
, gap := cumsum(c(diff(N), 0L) > 1L)][
, M := first(N) + 1L, by = gap]
# non-equi anti-join and recast
long[!nlvl[N > M], on = .(rn, lvl >= M, lvl < N)][
, .(No = paste(V1, collapse = ".")), by = rn]
解释
如果我理解正确的话,字符串序列表示大纲中的部分编号,该编号由于插入虚假的附加级别而被扭曲。OP正在寻找删除这些附加级别的方法
那么,让我们假设一些对大纲各部分进行编号的规则:
节数差距:在同一级别上,节数始终提前1。
例如,遵循第4.1.3节
- 通过
4.1.4
(在第3节中前进)
- 或通过
4.2
(如果父级为高级)
- 或通过
5
(前进到下一章)
级别差距:子级别始终比父级别低1个级别。子级上的节编号从1开始。
例如,章节4.1.3
后面可以是4.1.3.1
小节,但不能是
4.1.3.1.1
从第3节级别跳到第5小节级别
由于OPs问题可能与情形2有关,我们需要用
与前面行相关的级别差距。作为修复,所有中间剩余水平将被删除。最后一个级别保持不变,因为它的编号可能是正确的
第一步包括添加行号、拆分“
处的字符串、强制将节号设置为整数以及为每行的级别编号。现在,章节编号采用长格式:
long
在下一步中,将识别出现在剖面层间隙之后的连续行条纹。节级别是属于一行的元素的数量N
<代码>间隙
标记在节级别中非法跳转之后出现的所有行M
表示根据上述规则2合法的最高区段等级
nlvl
在最后一步中,通过非等反连接从long
中消除额外的杂散电平。然后,通过将各部分粘贴在一起重新创建节号
为了进行比较,我们可以将结果与原始数据结合起来:
long[!nlvl[N > M], on = .(rn, lvl >= M, lvl < N)][
, .(No = paste(V1, collapse = ".")), by = rn][DT, on = "rn"]
资料
OP发布的数据的扩展版本
library(data.table)
DT <- data.table(No = c(
"48.8.1.1.",
"48.8.1.2.",
"48.8.2." ,
"48.9." ,
"48.10." ,
"48.11." ,
"48.11.1." ,
"48.11.1.1." ,
"48.11.1.2." ,
"48.11.1.2.2.2.2.1.",
"48.11.1.2.2.2.2.2.",
"48.11.1.2.2.3.",
"48.11.2.",
"48.11.2.1.",
"48.11.2.1.1.",
"48.11.3.",
"48.11.3.3.3.1.",
"50."
))
库(data.table)
DT您提供了问题,但提供了没有问题的数据。请编辑您的问题以使其更易于理解。@NelsonGon:嘿,我已经编辑了问题。请包括您迄今为止所做的尝试。我看到您提供了输入数据的示例。还请添加(1)您想要的结果,以及(2)到目前为止您尝试将输入转换为结果的代码。那么为什么48.11.1.1
和48.8.1.1.
不是垃圾?只有当字符串为9个字符但我的字符串没有固定长度时,它才会起作用。请尝试编辑。另外,最好准确地表示数据的外观。使用dput
添加样本数据。非常好。在我注意到你对问题的中间评论和编辑后,我担心测试用例的数量太少,无法充分测试相当复杂的逻辑。耶,我在代码中做了一些更改,现在工作正常。你在代码中做了哪些更改?请让我知道如何改进我的答案-谢谢。
rn V1 lvl
1: 1 48 1
2: 1 8 2
3: 1 1 3
4: 1 1 4
5: 2 48 1
6: 2 8 2
[...]
25: 9 48 1
26: 9 11 2
27: 9 1 3
28: 9 2 4
29: 10 48 1
30: 10 11 2
31: 10 1 3
32: 10 2 4
33: 10 2 5
34: 10 2 6
35: 10 2 7
36: 10 1 8
37: 11 48 1
38: 11 11 2
39: 11 1 3
40: 11 2 4
41: 11 2 5
42: 11 2 6
43: 11 2 7
44: 11 2 8
45: 12 48 1
46: 12 11 2
47: 12 1 3
48: 12 2 4
49: 12 2 5
50: 12 3 6
51: 13 48 1
52: 13 11 2
53: 13 2 3
54: 14 48 1
55: 14 11 2
56: 14 2 3
57: 14 1 4
58: 15 48 1
59: 15 11 2
60: 15 2 3
61: 15 1 4
62: 15 1 5
63: 16 48 1
64: 16 11 2
65: 16 3 3
66: 17 48 1
67: 17 11 2
68: 17 3 3
69: 17 3 4
70: 17 3 5
71: 17 1 6
72: 18 50 1
rn V1 lvl
nlvl
rn N gap M
1: 1 4 0 5
2: 2 4 0 5
3: 3 3 0 5
4: 4 2 0 5
5: 5 2 0 5
6: 6 2 0 5
7: 7 3 0 5
8: 8 4 0 5
9: 9 4 1 5
10: 10 8 1 5
11: 11 8 1 5
12: 12 6 1 5
13: 13 3 1 5
14: 14 4 1 5
15: 15 5 1 5
16: 16 3 2 4
17: 17 6 2 4
18: 18 1 2 4
long[!nlvl[N > M], on = .(rn, lvl >= M, lvl < N)][
, .(No = paste(V1, collapse = ".")), by = rn][DT, on = "rn"]
rn No i.No
1: 1 48.8.1.1 48.8.1.1.
2: 2 48.8.1.2 48.8.1.2.
3: 3 48.8.2 48.8.2.
4: 4 48.9 48.9.
5: 5 48.10 48.10.
6: 6 48.11 48.11.
7: 7 48.11.1 48.11.1.
8: 8 48.11.1.1 48.11.1.1.
9: 9 48.11.1.2 48.11.1.2.
10: 10 48.11.1.2.1 48.11.1.2.2.2.2.1.
11: 11 48.11.1.2.2 48.11.1.2.2.2.2.2.
12: 12 48.11.1.2.3 48.11.1.2.2.3.
13: 13 48.11.2 48.11.2.
14: 14 48.11.2.1 48.11.2.1.
15: 15 48.11.2.1.1 48.11.2.1.1.
16: 16 48.11.3 48.11.3.
17: 17 48.11.3.1 48.11.3.3.3.1.
18: 18 50 50.
library(data.table)
DT <- data.table(No = c(
"48.8.1.1.",
"48.8.1.2.",
"48.8.2." ,
"48.9." ,
"48.10." ,
"48.11." ,
"48.11.1." ,
"48.11.1.1." ,
"48.11.1.2." ,
"48.11.1.2.2.2.2.1.",
"48.11.1.2.2.2.2.2.",
"48.11.1.2.2.3.",
"48.11.2.",
"48.11.2.1.",
"48.11.2.1.1.",
"48.11.3.",
"48.11.3.3.3.1.",
"50."
))