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.