Панды скользящий датафрейм для создания кластеров - PullRequest
0 голосов
/ 28 августа 2018

Я пытаюсь создать фрейм данных в python, делая кумулятивную сумму для определенного размера окна (x) с фиксированными приращениями (y), и если сумма больше, чем предопределенное значение (z), я хочу добавить значения (в зависимости от столбца) для другого кадра данных. Я могу использовать тонну циклов for, чтобы сделать это, но это кажется неэффективным.

Чтобы подробно описать проблему, вот как выглядит мой фрейм данных:

│ Start  │ End    │ Count │
├────────┼────────┼───────┤
│ 49076  │ 49095  │ 1     │
│ 50296  │ 50318  │ 1     │
│ 53291  │ 53308  │ 1     │
│ 56213  │ 56232  │ 3     │
│ 86489  │ 86508  │ 13    │
│ 86489  │ 86508  │ 7     │
│ 150696 │ 150713 │ 1     │
│ 174807 │ 174824 │ 1     │
│ 192491 │ 192508 │ 1     │
│ 203977 │ 203996 │ 1     │
│ 269679 │ 269696 │ 1     │
⋮

и окно работает при запуске вместо строки. Это означает, что если окно равно 10000 (x), то первое окно начнется с 49076 и закончится на 59076. С приращением 1000 (y) второе окно начнется с 50076 и закончится на 60076 и так далее. Теперь, если в любом из этих окон сумма столбца Count превышает порог (z), я хочу, чтобы min (Start) и max (End) вместе с sum для этого окна были сохранены в виде строки в новом фрейме данных (с перекрывающимися окнами). объединенный). Примечание: окно теоретически также может начинаться с 0/1 и заканчиваться на max (End).

Каков наиболее оптимальный способ сделать это (используя панд, numpy или scikit-learn)?

Edit: я сделал диаграмму, чтобы примерно описать то, что я хочу. В моём случае pandas dataframe фактически описывает сегменты * длинной строки. То, что мне нужно, это другой фрейм данных, где, если сумма сегментов в окне превышает порог, я получаю начало самого левого сегмента и конец самого правого сегмента в новом фрейме данных. * - (если мы посчитаем, что столбец count содержит только один)

enter image description here

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

1 Ответ

0 голосов
/ 12 сентября 2018

Хорошо - я пытаюсь опубликовать временное решение, которое я сделал: на самом деле не рекомендую никому пробовать его.

for i in positiveFrame.chr.unique():
    workingFrame = positiveFrame[positiveFrame['chr'] == i]
    totalPeaks = workingFrame['count'].sum()
    # print ("Total amount of peaks in contig: ", i, ": ", totalPeaks)
    if totalPeaks < minimumSum:
        continue
    hits = workingFrame.start.tolist()
    runningFrame = pd.DataFrame({'start': range(1, lengthFile[str(i)]), 'hit': 0})
    runningFrame.loc[runningFrame.start.isin(hits), ['hit']] = 1
    for k in range(0, runningFrame.shape[0], incrementSize):
        z = runningFrame[k:k + incrementSize]
        if (z['hit'].sum() > 49):
            #print("banzai\n")
            positiveClusterChr.append(i)
            positiveClusterStart.append(z['hit'].eq(1).idxmax())
            positiveClusterEnd.append(z.hit[::-1].idxmax())

По сути, здесь происходит то, что я создаю другой фрейм данных с координатами, начинающимися с 0 и заканчивающимися на макс (конец) - этот шаг крайне неэффективен и занимает много памяти. В этом случае длина определяется массивом для каждого уникального chr. На следующем шаге я назначаю хиты (числа) позициям, которые соответствуют моему входному фрейму данных - на основе начальной позиции. И на последнем шаге я обхожу расширенный фрейм данных, каждый раз разрезая 1000 строк, а затем суммируя попадания. А для окон или срезов данных, которые совпадают, я беру минимальные и максимальные координаты и сохраняю их в массиве. Глючный, крайне неэффективный и избыточный код, но каким-то образом работающий на минимальном уровне.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...