У меня может быть замысловатое решение для вас:
Сначала я конвертирую ваши диапазоны в list
из tuples
из int
:
import pandas as pd
r = ["12-48", "40-80", "60-105", "110-130", "75-400"]
r = [tuple(map(int, z.split("-"))) for z in r]
# [(12, 48), (40, 80), (60, 105), (110, 130), (75, 400)]
Затем яПереберите все диапазоны и удалите все, которые полностью инкапсулированы другим диапазоном.Например: (110, 130)
находится в пределах (75, 400)
:
hold = []
for idx1 in range(len(r)):
start_1, stop_1 = r[idx1]
for idx2, (start_2, stop_2) in enumerate(r):
if idx1 == idx2:
continue
if start_2 < start_1 and stop_1 < stop_2:
hold.append(idx1)
while hold:
del r[hold.pop()]
# [(12, 48), (40, 80), (60, 105), (75, 400)]
Наконец, используя pandas.DataFrame
, я вычисляю перекрытие и процентное перекрытие;пометьте строки, которые соответствуют критериям исключения (перекрытие> 10 и%> 0,2).Эти строки затем удаляются в обратном порядке, и перекрытия проверяются снова после каждого удаления до тех пор, пока не удастся удалить больше строк.
Затем DataFrame преобразуется обратно в список строк в том же формате, в котором они были предоставлены.дюймы
df = pd.DataFrame(r, columns=["start", "stop"]).sort_values("start")
df["length"] = df["stop"] - df["start"]
df["bool_1"], df["bool_2"] = True, True
while any(df["bool_1"].eq(True) & df["bool_2"].eq(True)):
df["overlap"] = df["stop"] - df["start"].shift(-1)
df["pc"] = df["overlap"] / df["length"]
df["bool_1"] = df["overlap"] > 10
df["bool_2"] = df["pc"] > 0.2
for i, row in df.sort_index(ascending=False).iterrows():
if row["bool_1"] == row["bool_2"] and row["bool_1"] is not False:
df.drop(i, inplace=True)
break
result = df["start"].astype("str").str.cat(df["stop"].astype("str"), sep="-").to_list()
# ['12-48', '40-80', '75-400']