2014-12-14 3 views
0

У меня есть эта Пандас dataframe df:Итерация Пандас dataframe над «N» следующих строк

station a_d direction 
    a  0  0 
    a  0  0 
    a  1  0 
    a  0  0 
    a  1  0 
    b  0  0 
    b  1  0 
    c  0  0 
    c  1  0 
    c  0  1 
    c  1  1 
    b  0  1 
    b  1  1 
    b  0  1 
    b  1  1 
    a  0  1 
    a  1  1 
    a  0  0 
    a  1  0 

Я бы назначить value_id, который увеличивает значение, когда изменение направления и относится только к последней паре стоимости первой станции он изменяется с другим значением [0,1] a_d. Я могу игнорировать последние (в этом примере последние две) строки данных. Другими словами:

station a_d direction id_value 
    a  0  0 
    a  0  0 
    a  1  0 
    a  0  0  0 
    a  1  0  0 
    b  0  0  0 
    b  1  0  0 
    c  0  0  0 
    c  1  0  0 
    c  0  1  1 
    c  1  1  1 
    b  0  1   
    b  1  1   
    b  0  1  1 
    b  1  1  1 
    a  0  1  1 
    a  1  1  1 
    a  0  0 
    a  1  0 

Использование df.iterrows() я пишу этот скрипт:

df['value_id'] = "" 
value_id = 0 
row_iterator = df.iterrows() 
for i, row in row_iterator: 
    if i == 0: 
     continue 
    elif (df.loc[i-1,'direction'] != df.loc [i,'direction']): 
     value_id += 1 
    for z in range(1,11): 
     if i+z >= len(df)-1: 
      break 
     elif (df.loc[i+1,'a_d'] == df.loc [i,'a_d']): 
      break 
     elif (df.loc[i+1,'a_d'] != df.loc [i,'a_d']) and (df.loc [i+2,'station'] == df.loc [i,'station'] and (df.loc [i+2,'direction'] == df.loc [i,'direction'])): 
      break 
     else: 
      df.loc[i,'value_id'] = value_id 

Это работает, но это очень медленно. С фреймом данных строк 10*10^6 мне нужен более быстрый способ. Есть идеи?

@ user5402 код работает хорошо, но я отмечаю, что break после последнего else сократить время вычислений также:

df['value_id'] = "" 
value_id = 0 
row_iterator = df.iterrows() 
for i, row in row_iterator: 
    if i == 0: 
     continue 
    elif (df.loc[i-1,'direction'] != df.loc [i,'direction']): 
     value_id += 1 
    for z in range(1,11): 
     if i+z >= len(df)-1: 
      break 
     elif (df.loc[i+1,'a_d'] == df.loc [i,'a_d']): 
      break 
     elif (df.loc[i+1,'a_d'] != df.loc [i,'a_d']) and (df.loc [i+2,'station'] == df.loc [i,'station'] and (df.loc [i+2,'direction'] == df.loc [i,'direction'])): 
      break 
     else: 
      df.loc[i,'value_id'] = value_id 
      break 
+0

Код, который вы отправили, похоже, не производит этот вывод. – DSM

+0

Я имею в виду, что я получаю '['', '', '', 0, 0, 0, 0, '', '', 1, 1, '', '', 1, 1, '', '', ] 'как столбец' value_id', который не соответствует столбцу 'id_value' вашего вывода. – DSM

+0

Вы не используете 'z' во внутреннем цикле for - на самом деле его можно полностью исключить. Разве вы не хотите использовать 'df.loc [i + z, ...' где-то в этом цикле? – ErikR

ответ

1

Вы не эффективно использовать z во внутреннем цикл. Вы никогда не получаете доступ к строке i+z. Вы получаете доступ к i-й строке и i+1-й строке и i+2-й строке, но никогда не i+z-й строке.

Вы можете заменить, что внутренний цикл с:

if i+1 > len(df)-1: 
    pass 
    elif (df.loc[i+1,'a_d'] == df.loc [i,'a_d']): 
    pass 
    elif (df.loc [i+2,'station'] == df.loc [i,'station'] and (df.loc [i+2,'direction'] == df.loc [i,'direction'])): 
    pass 
    else: 
    df.loc[i,'value_id'] = value_id 

Обратите внимание, что я также немного оптимизировали второй elif, потому что в этот момент вы уже знаете df.loc[i+1,'a_d'] не равна df.loc [i,'a_d'].

Не нужно перегибать z сэкономит много времени.

+0

Да, это работает, но я понимаю, что' break' после последнего 'else' во внутреннем цикле for делает скрипт так же быстро, как скрипт без для цикла –

+0

Вам не нужна строка 'for z in range (1,11)' в вашем коде вообще. Бьюсь об заклад, вам нужно добавить оператор 'break', потому что у вас все еще есть строка' for z ... 'в вашем коде. Просто избавитесь от него и переместите тело цикла налево на один уровень. – ErikR

+0

Возможно, вы не понимаете мой комментарий. Я говорю, что ваше предлагаемое решение занимает то же самое время, что и с 'break' после последнего' else'. Я просто редактирую свой пост. Вы согласны? –

Смежные вопросы