Нужно вставить строки в df в соответствии с разницей между двумя строками - PullRequest
0 голосов
/ 26 февраля 2020

Я использовал программу для вычисления значений пи по геному. Однако эта программа не будет выводить нулевые значения. Мне нужно определить windows, что он пропущен, и добавить нули.

Вот мой файл:

CHROM   BIN_START   BIN_END N_VARIANTS  PI
scaffold_1  1   10000   103 0.00409768
scaffold_1  10001   20000   67  0.00421737
scaffold_1  20001   30000   129 0.00856667
scaffold_1  30001   40000   142 0.00905
scaffold_1  40001   50000   188 0.0125167
scaffold_1  50001   60000   210 0.014
scaffold_1  60001   70000   158 0.0105333
scaffold_1  70001   80000   198 0.0131833
scaffold_1  80001   90000   183 0.0121833
scaffold_1  100001  110000  256 0.0170667
scaffold_1  110001  120000  263 0.0175667

Если вы видите, что окно, появившееся из 90001 и 100000, отсутствует. На самом деле мне просто нужно добавить строку с 0 в столбце PI.

Я подумал go об этом, чтобы добавить условное утверждение, что если разрыв между первым и вторым значением превышает 10000, добавить строку с нулем. Однако, из-за больших промежутков (то есть пропадает 2 или 3 ячейки подряд), я боюсь, что в результате я пропущу их при таком подходе.

1 Ответ

0 голосов
/ 26 февраля 2020
from io import StringIO
import pandas as pd
import numpy as np

df = pd.read_csv(StringIO(
'''CHROM BIN_START BIN_END N_VARIANTS PI
scaffold_1 1 10000 103 0.00409768
scaffold_1 10001 20000 67 0.00421737
scaffold_1 20001 30000 129 0.00856667
scaffold_1 30001 40000 142 0.00905
scaffold_1 40001 50000 188 0.0125167
scaffold_1 80001 90000 183 0.0121833
scaffold_1 100001 110000 256 0.0170667
scaffold_1 110001 120000 263 0.0175667
scaffold_2 10001 20000 10 0.003
scaffold_2 30001 40000 10 0.003
'''), sep=' ')

def fill_function(group_df, step_size=10000):
    bin_start_vals = np.arange(0, group_df['BIN_START'].max() + step_size, step=step_size)
    # set our index to BIN_START so we dont lose what we have and then reindex to the full range of values
    group_df = group_df.set_index('BIN_START').reindex(bin_start_vals)
    # reset to fix up columns
    group_df = group_df.reset_index()
    # fill in empty data
    group_df['BIN_END'] = group_df['BIN_START'] + step_size

    # drop CHROM, we already have from groupby and fillna with 0
    return group_df.drop('CHROM', axis=1).fillna(0)

dfx = df.groupby(['CHROM']).apply(fill_function)
dfx.reset_index(level=0)


CHROM   BIN_START   BIN_END N_VARIANTS  PI
0   scaffold_1  1   10001   103.0   0.004098
1   scaffold_1  10001   20001   67.0    0.004217
2   scaffold_1  20001   30001   129.0   0.008567
3   scaffold_1  30001   40001   142.0   0.009050
4   scaffold_1  40001   50001   188.0   0.012517
5   scaffold_1  50001   60001   0.0 0.000000
6   scaffold_1  60001   70001   0.0 0.000000
7   scaffold_1  70001   80001   0.0 0.000000
8   scaffold_1  80001   90001   183.0   0.012183
9   scaffold_1  90001   100001  0.0 0.000000
10  scaffold_1  100001  110001  256.0   0.017067
11  scaffold_1  110001  120001  263.0   0.017567
0   scaffold_2  1   10001   0.0 0.000000
1   scaffold_2  10001   20001   10.0    0.003000
2   scaffold_2  20001   30001   0.0 0.000000
3   scaffold_2  30001   40001   10.0    0.003000

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

В приведенном выше коде я удалил еще несколько ваших строки для примера и добавил scaffold_2, чтобы показать, как мы будем делать это с помощью scaffold, а не глобально.

Допущения:

Каждая хромосома имеет различный диапазон BIN_START / END, и вам следует избегать большого числа конечных нулей для небольших лесов, поэтому вам нужно использовать groupby

Вы всегда начинаете с 1 для каркаса, независимо от того, есть ли у него данные или нет, и вы хотите включить те, которые имеют 0.

...