Как суммировать перекрывающиеся интервалы без включения перекрытия

Мы собрали данные, в которых мы измеряли длину вдоль измерительной ленты, где определенные виды перекрывали ее. В некоторых случаях несколько видов могут перекрывать его в одном и том же месте. Мне нужно выяснить, какая часть ленты была перекрыта растениями, не подсчитывая одинаковую длину ленты дважды, когда несколько растений перекрывают одно и то же место, и мне нужно сделать это, сгруппировав по типу растительности (например, куст, дерево и т. д.). Итак, отвечаю на вопрос, "сколько ленты покрыто кустарниками?" Например.

Например, представьте, что пунктирная линия — это измерительная лента, а звездочки — это разные кусты, перекрывающие ленту. Это то, что мои данные по существу представляют прямо сейчас. Если бы я посчитал длину всех кустов, то получил бы большое число, большее, чем реальная длина ленты...

  ***    **    *********
   ****       **     *******
----------------------------

...но это то, что мне нужно выяснить, реальную длину ленты, покрытой любым кустом:

  *****  **   **************
----------------------------

Я надеюсь, что это имеет смысл, но вот несколько примеров для дальнейшего объяснения, если это необходимо:

Пример: Представьте, что я столкнулся с деревьями Дуга Фир, которые перекрывали измерительную ленту, простирающуюся от 4-футовой отметки до 10-футовой отметки и от 20-футовой отметки до 25-футовой отметки. Я также встретил ели, перекрывающие ленту от 7 до 14 футов. Мне нужно знать общую длину перекрытия видов деревьев (это оба дерева), поэтому мне нужно будет суммировать длины этих диапазонов как для ели, так и для пихты Дуга. Однако, если я просто просуммирую все диапазоны обычным образом, то в итоге я посчитаю область от 7 до 10 футов (сумма = 3 фута) дважды, а не один раз, где и Спрус, и Дуг Фирс покрывали ленту. Итак, мне нужно будет вычесть 3' из конечного значения, чтобы эта часть измерительной ленты не учитывалась более одного раза. Итак, мои диапазоны 6 футов, 5 футов и 7 футов, что в сумме составляет 18 футов. После вычитания перекрывающихся 3 футов это дает в общей сложности 15 футов, где деревья перекрывают ленту.

Примерная таблица ниже. У меня уже есть данные SPECIES, START, END, TYPE и SUM. Что мне нужно, чтобы Excel помог мне вычислить, так это значения, показанные под таблицей, которые представляют собой суммы после учета перекрытия нескольких видов. Например, если куст X перекрывается от 10 до 20 футов, а куст Y перекрывается от 13 до 25 футов, общее перекрытие будет от 10 до 25 футов, то есть пятнадцать футов перекрытия. Не перекрытие 22 фута, как было бы, если бы вы считали каждый из диапазонов отдельно.)

SPECIES START(ft) END(ft) TYPE  SUM (ft)
Dogwood 40.3      40.9    Shrub   0.6
Cedar   52.8      79.5    Tree    26.7
Dogwood 50.2      55.6    Shrub   5.4
Rose    53.8      54.4    Shrub   0.6
Alder   88.2      95.5    Tree    7.3
Clover  75.8      76.2    Forb    0.4
Bunch   82.8      90.3    Grass   7.5
Poa     86.1      95.3    Grass   9.2
Sedge   99.4      100.9   Grass   1.5
Bttrcp  74.5      101.3   Forb    26.8
Elder   105.8     120.3   Shrub   14.5
Bttrcp  110.3     120.2   Forb    9.9
Cedar   90.4      99.9    Tree    9.5



SHRUB SUM   TREE SUM    FORB SUM    GRASS SUM
  20.5       38.4         35.4         14

Любое руководство в выяснении этого будет высоко оценено!


person Tim Miller    schedule 09.05.2017    source источник
comment
Как из этой таблицы определить перекрытие каждого растения?   -  person jivko    schedule 09.05.2017
comment
Как есть, вам нужно просто просмотреть и выяснить, где есть перекрытия. Например, глядя на него, я вижу, что у травы Гроздь изменяется с 82,8 до 90,3, а у мятлика — с 86,1 до 95,3, поэтому они перекрываются между 86,1 и 90,3. 90,3-86,1 = перекрытие 4,2.   -  person Tim Miller    schedule 09.05.2017


Ответы (1)


Вот некоторый псевдокод, который может работать. Кроме того, это оценивается только для каждого ТИПА. Чтобы получить всю область, повторите для каждого ТИПА:

get_max_area(data):
    sort(data, START)
    for i <- 1 to n:
        for j <- i to n:
            if data[j][START] < data[i][START]:         // Two segments overlap
                if data[j][END] < data[i][END]:         // j is fully contained within i
                    ignore(data[j])
                else:                                   // They just overlap
                    merge(data[i], data[i + 1])
                                                        // ELSE: independent segments

    return sum(data[SUM])

Игнорирование означает, что сегмент больше не тестируется. Слияние означает создание сегмента a(i, j) и b(x, y) новым сегментом c(i, y). Это просто быстрый подход, и он занимает O (n ^ 2). Должен быть лучший подход.

person mmiranda96    schedule 09.05.2017
comment
Можете ли вы помочь мне с тем, как я буду интегрировать это? Год назад я бы точно знал, что делать, но, похоже, мои навыки VBA улетучились. - person Tim Miller; 10.05.2017
comment
У меня нет такого большого опыта в VBA, извините. - person mmiranda96; 11.05.2017