Для петли панд и клева: производительность - PullRequest
0 голосов
/ 07 сентября 2018

Я закодировал следующее для цикла. Основная идея заключается в том, что при каждом появлении «D» в столбце «A_D» он ищет все возможные случаи, когда должны возникать определенные условия. Когда все условия проверены, значение добавляется в список.

a = []
for i in df.index:
    if df['A_D'][i] == 'D':
         if df['TROUND_ID'][i] == '        ':
             vb = df[(df['O_D'] == df['O_D'][i])
             & (df['A_D'] == 'A' )
             & (df['Terminal'] == df['Terminal'][i])
             & (df['Operator'] == df['Operator'][i])]

            number = df['number_ac'][i]
            try: ## if all the conditions above are verified a value is added to a list
                x = df.START[i] - pd.Timedelta(int(number), unit='m')
                value = vb.loc[(vb.START-x).abs().idxmin()].FlightID
            except: ## if are not verified, several strings are added to the list
                value = 'No_link_found'
        else:
            value = 'Has_link'
    else:
        value = 'IsArrival'
a.append(value)

Моя главная проблема в том, что в df миллионы строк, поэтому цикл for слишком трудоемкий. Есть ли векторизованное решение, где мне не нужно использовать цикл for?

1 Ответ

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

Исходный набор улучшений: используйте 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...