Исходный набор улучшений: используйте apply
вместо цикла; создайте второй кадр данных в начале строк, где df["A_D"] == "A"
; и векторизовать значение x
.
arr = df[df["A_D"] == "A"]
# if the next line is slow, apply it only to those rows where x is needed
df["x"] = df.START - pd.Timedelta(int(df["number_ac"]), unit='m')
def link_func(row):
if row["A_D"] != "D":
return "IsArrival"
if row["TROUND_ID"] != " ":
return "Has_link"
vb = arr[arr["O_D"] == row["O_D"]
& arr["Terminal"] == row["Terminal"]
& arr["Operator"] == row["Operator"]]
try:
return vb.loc[(vb.START - row["x"]).abs().idxmin()].FlightID
except:
return "No_link_found"
df["a"] = df.apply(link_func, axis=1)
Использование apply
является , очевидно, более эффективным , но автоматически не векторизует вычисление. Но поиск значения в arr
на основе каждой строки df
отнимает много времени, как бы эффективно это ни реализовывалось. Подумайте, можно ли как-то преобразовать две части исходного кадра данных (где df["A_D"] == "A"
и df["A_D"] == "D"
соответственно) в широкий формат.
РЕДАКТИРОВАТЬ: Возможно, вы сможете ускорить запрос arr
путем сохранения строк запроса в df
, например:
df["query_string"] = ('O_D == "' + df["O_D"]
+ '" & Terminal == "' + df["Terminal"]
+ '" & Operator == "' + df["Operator"] + '"')
def link_func(row):
vb = arr.query(row["query_string"])
try:
row["a"] = vb.loc[(vb.START - row["x"]).abs().idxmin()].FlightID
except:
row["a"] = "No_link_found"
df.query('(A_D == "D") & (TROUND_ID == " ")').apply(link_func, axis=1)