Программно определить шаблоны в позиционных данных для получения столбцов - Стандартное отклонение? - PullRequest
0 голосов
/ 13 марта 2012

У меня есть ряд элементов в базе данных MySQL.

У каждого элемента есть четыре характеристики, связанные с ним:
abs_left (элементы, оставленные в самом верхнем положении)
abs_center (положение элементов в центре)
abs_right (элементы в крайнем правом положении)
строка (вертикальная позиция элементов)

Внутри порции данных я знаю, что элементы выровнены по столбцам, но я не знаю, сколько существует столбцов.Числа abs_left, abs_center и abs_right также не являются точными и варьируются довольно значительно (например, abs_right одного элемента может немного перекрывать abs_left другого элемента, если они находятся в разных столбцах).Строка пунктов, не меняется и должна быть правильной.Однако не у каждой строки в блоке данных есть элемент в каждом столбце.В результате, учитывая какую-либо одну строку данных в чанке, я не могу сказать, сколько существует столбцов.

Я хотел бы определить две вещи:
1) Количество столбцов в чанкерассматриваемые данные.
2) Приблизительные границы каждого из этих столбцов.

Я почти уверен, что математика может быть применена, чтобы помочь мне сделать это, но я не совсем уверенкак это сделать концептуально.Я думаю, что можно использовать стандартное отклонение, но я не уверен, как применить его к числу столбцов X.

Любая помощь, которую вы, ребята, можете предоставить, или идеи о том, как ее атаковать,с благодарностью!

[отредактировано для добавления данных выборки]
Ниже приведены сводные данные по запросам, которые уже использовались для округления ответов.Что касается сводных данных, они менее точны, но, вероятно, дадут представление о том, с чем сталкиваются.Часть "строка" исключена из сводных данных, поскольку все было объединено, но у меня есть понятие строки в полном наборе данных.

"section_id"    "abs_left"  "abs_right" "count"
"1" "0"     "4"     "144"
"1" "1"     "4"     "4"
"1" "8"     "12"    "152"
"1" "40"    "59"    "4"
"1" "41"    "57"    "2"
"1" "41"    "60"    "45"
"1" "43"    "44"    "2"
"1" "48"    "63"    "88"
"1" "50"    "65"    "1"
"1" "54"    "64"    "11"
"3" "0"     "15"    "2"
"3" "1"     "10"    "4"
"3" "58"    "60"    "1"
"3" "58"    "69"    "3"
"3" "63"    "70"    "5"
"3" "66"    "72"    "10"
"3" "67"    "73"    "5"
"3" "82"    "87"    "3"
"3" "96"    "104"   "6"
"3" "100"   "104"   "2"
"3" "114"   "122"   "25"
"3" "129"   "137"   "15"
"3" "130"   "137"   "20"
"3" "133"   "137"   "1"
"3" "143"   "151"   "38"
"3" "146"   "151"   "1"
"3" "165"   "172"   "3"
"3" "168"   "175"   "36"
"4" "4"     "10"    "6"
"4" "4"     "21"    "18"
"4" "5"     "25"    "9"
"4" "5"     "30"    "10"
"4" "5"     "34"    "21"
"4" "6"     "41"    "7"
"4" "6"     "43"    "1"
"4" "55"    "64"    "3"
"4" "70"    "76"    "3"
"4" "75"    "83"    "42"
"4" "76"    "84"    "4"
"4" "77"    "82"    "11"
"4" "93"    "100"   "16"
"4" "95"    "101"   "13"
"4" "95"    "101"   "7"
"4" "104"   "110"   "2"
"4" "108"   "116"   "27"
"4" "123"   "130"   "37"
"4" "139"   "143"   "1"
"4" "139"   "146"   "75"
"4" "143"   "147"   "2"

Раздел 1 имеет 3 столбца.
Раздел 3 содержит 7 столбцов.
Раздел 4 содержит 7 столбцов.

1 Ответ

1 голос
/ 13 марта 2012

План атаки

  1. Проецируйте каждый диапазон элементов на числовую линию, «отбрасывая тень», где она находится
  2. Проанализируйте проекцию, чтобы найти ребра, а затем пронумеруйте каждыйнепрерывная «тень» в виде столбца
  3. Сопоставьте каждый элемент с номером его столбца, затем проанализируйте карту

Сначала создайте «числовую строку» из целых чисел, охватывающую доменвходных данных (ниже 0-255)

create table integers as
select
  bit1.n+bit2.n+bit3.n+bit4.n+bit5.n+bit6.n+bit7.n+bit8.n as n
from
             (select 0 n union all select   1) bit1
  cross join (select 0 n union all select   2) bit2
  cross join (select 0 n union all select   4) bit3
  cross join (select 0 n union all select   8) bit4
  cross join (select 0 n union all select  16) bit5
  cross join (select 0 n union all select  32) bit6
  cross join (select 0 n union all select  64) bit7   
  cross join (select 0 n union all select 128) bit8
;

Затем для каждого section_id возьмите проекцию диапазона (abs_left, abs_right) на числовую строку и сохраните во временной таблице

create table temp_item_distribution (
  is_start_of_column int
, column_number int
, primary key (section_id, n)
) as
select
  section_id
, n
, sum(is_match) as matches
from
  (
    select
      section_id
    , n
    , 0 as is_match
    from 
      (select distinct section_id from items) s
      cross join integers
    union all
    select
      section_id
    , n
    , 1 
    from
      items i
      inner join integers z
        on z.n between i.abs_left and i.abs_right
  ) t
group by
  section_id
, n;

Теперь найдите и пометьте крайний левый край каждого столбца

  update
    temp_item_distribution r
    left join temp_item_distribution l
      on l.section_id = r.section_id
      and l.n = r.n - 1
  set
    r.is_start_of_column = case when coalesce(l.matches, 0) = 0 and r.matches > 0 then 1 else 0 end
  ;

Теперь, используя эту метку, мы можем нумеровать и пометить сами столбцы

  update
    temp_item_distribution t
    inner join (
        select 
          r.section_id
        , r.n
        , sum(l.is_start_of_column) as column_number
        from
          temp_item_distribution l
          inner join temp_item_distribution r
            on l.section_id = r.section_id 
             and l.n <= r.n
        group by
          r.section_id
        , r.n
      ) s
      on t.section_id = s.section_id
      and t.n = s.n
  set
    t.column_number = s.column_number
  where
    t.matches > 0
  ;

Теперь мы можем отобразить элементы обратно на столбцы

  create table temp_items_in_columns as
  select
    i.section_id
  , i.abs_left
  , i.abs_right
  , t.column_number
  from
    items i
    inner join temp_item_distribution t
      on i.section_id = t.section_id 
      and i.abs_left = t.n
  ;

Теперь мы можем ответить на вопрос (..!)

  select
    section_id
  , max(column_number) as number_of_columns
  from
    temp_items_in_columns
  group by
    section_id
  ;

+------------+-------------------+
| section_id | number_of_columns |
+------------+-------------------+
|          1 |                 3 |
|          3 |                 8 |
|          4 |                 7 |
+------------+-------------------+

И края:

  select
    section_id
  , column_number
  , min(abs_left)                                 as far_left
  , round(avg(abs_left) - stddev(abs_left),1)     as 1_sigma_left
  , round(avg(abs_right) + stddev(abs_right),1)   as 1_sigma_right
  , max(abs_right)                                as far_right
  from
    temp_items_in_columns
  group by
    section_id
  , column_number
  ;

+------------+---------------+----------+--------------+---------------+-----------+
| section_id | column_number | far_left | 1_sigma_left | 1_sigma_right | far_right |
+------------+---------------+----------+--------------+---------------+-----------+
|          1 |             1 |        0 |          0.0 |           4.0 |         4 |
|          1 |             2 |        8 |          8.0 |          12.0 |        12 |
|          1 |             3 |       40 |         40.3 |          63.9 |        65 |
|          3 |             1 |        0 |          0.0 |          15.0 |        15 |
|          3 |             2 |       58 |         58.6 |          73.4 |        73 |
|          3 |             3 |       82 |         82.0 |          87.0 |        87 |
|          3 |             4 |       96 |         96.0 |         104.0 |       104 |
|          3 |             5 |      114 |        114.0 |         122.0 |       122 |
|          3 |             6 |      129 |        129.0 |         137.0 |       137 |
|          3 |             7 |      143 |        143.0 |         151.0 |       151 |
|          3 |             8 |      165 |        165.0 |         175.0 |       175 |
|          4 |             1 |        4 |          4.2 |          39.9 |        43 |
|          4 |             2 |       55 |         55.0 |          64.0 |        64 |
|          4 |             3 |       70 |         71.8 |          84.4 |        84 |
|          4 |             4 |       93 |         93.4 |         101.1 |       101 |
|          4 |             5 |      104 |        104.0 |         116.0 |       116 |
|          4 |             6 |      123 |        123.0 |         130.0 |       130 |
|          4 |             7 |      139 |        138.4 |         147.0 |       147 |
+------------+---------------+----------+--------------+---------------+-----------+

(с использованием интервала 1 стандартного отклонения, который составляет около 68% для нормальногоразмером взносов.Смотри: http://en.wikipedia.org/wiki/Standard_deviation)

...