R: Упорядочивание данных в ячейке фрейма данных - PullRequest
0 голосов
/ 15 февраля 2019

У меня огромный фрейм данных из нескольких столбцов, один из столбцов содержит такие данные

       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."      

нет фиксированной последовательности в порядке упорядочения данных.

ПРОБЛЕМА:

вместо

   "48.11.1.2.1."  

некоторые значения не в правильном порядке, например:

   "48.11.1.2.2.2.2.1"   

no из 2 является дополнительным.Как убрать лишние числа 2.

Я попробовал какой-то метод, например сброс индекса и т. Д., Не сработало.пожалуйста, нужно какое-то предложение.

Ответы [ 2 ]

0 голосов
/ 18 февраля 2019

В предположении, что последовательность символьных строк представляет нумерацию разделов в схеме, вот возможное решение:

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]
    rn          No
 1:  1    48.8.1.1
 2:  2    48.8.1.2
 3:  3      48.8.2
 4:  4        48.9
 5:  5       48.10
 6:  6       48.11
 7:  7     48.11.1
 8:  8   48.11.1.1
 9:  9   48.11.1.2
10: 10 48.11.1.2.1
11: 11 48.11.1.2.2
12: 12 48.11.1.2.3
13: 13     48.11.2
14: 14   48.11.2.1
15: 15 48.11.2.1.1
16: 16     48.11.3
17: 17   48.11.3.1
18: 18          50

Объяснение

Если я правильно понимаю, последовательность строк символов представляет нумерацию разделов в схеме, которая была искажена при вставке ложных дополнительных уровней.ОП ищет метод удаления этих дополнительных уровней.

Итак, давайте предположим некоторые правила нумерации разделов схемы:

  1. Разрыв в номерах разделов: на том жеуровень, номера разделов всегда увеличиваются на 1.
    Например, за разделом 4.1.3 следует либо
    • * 4.1.4 (переход на уровень 3 раздела)
    • или 4.2 (если родительский уровень повышен)
    • или 5 (переход к следующей главе).
  2. Разрыв в уровнях: дочерний уровень всегда равен 1 уровнюниже уровня родителей.Нумерация разделов на дочернем уровне начинается с 1.
    Например, за разделом 4.1.3 может следовать 4.1.3.1 в качестве подраздела, но не на 4.1.3.1.1, который переходит с уровня раздела 3 на подпод подразделуровень раздела 5.

Поскольку вопрос ОП может быть связан с ситуацией 2, нам нужно идентифицировать строки с пропуском в уровнях относительно предыдущих строк.В качестве исправления все промежуточные избыточные уровни будут удалены.Последний уровень сохраняется, поскольку он предположительно имеет правильную нумерацию.

Первый шаг состоит из добавления номеров строк, разбиения строк символов в ".", приведения чисел в секции к целому числу и нумерации уровней для каждого из них.строка.Теперь номера разделов представлены в длинном формате:

 long
    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

На следующем шаге идентифицируются непрерывные полосы строк, которые появляются после пробела на уровне раздела.Уровень раздела - это число N элементов, принадлежащих строке.gap отмечает все строки, которые появляются после недопустимого перехода на уровне раздела.M обозначает максимальный уровень раздела, который был бы законным в соответствии с приведенным выше правилом 2.

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

На последнем этапе дополнительные ложные уровни удаляются из *От 1056 * до неэквивалентного анти-объединения .Затем номера секций воссоздаются путем склеивания частей.

Для сравнения мы можем объединить результат с исходными данными:

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."
))
0 голосов
/ 15 февраля 2019

Попробуйте:

РЕДАКТИРОВАТЬ ::

df$No<-stringr::str_remove_all(df$No,"2.{1,}(?=2.{3,})")

Результат:

             No
1     48.8.1.1.
2     48.8.1.2.
3       48.8.2.
4         48.9.
5        48.10.
6        48.11.
7      48.11.1.
8    48.11.1.1.
9    48.11.1.2.
10 48.11.1.2.1.

ОРИГИНАЛ ::

df$No<-substring(df$No,1,9)

Предполагается, что самая длинная строка состоит из 9 символов.Все остальное удалено.Результат:

df

              No
    1  48.8.1.1.
    2  48.8.1.2.
    3    48.8.2.
    4      48.9.
    5     48.10.
    6     48.11.
    7   48.11.1.
    8  48.11.1.1
    9  48.11.1.2
    10 48.11.1.2

Данные:

df<-read.table(text='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." ',header=T,stringsAsFactors=F)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...