2013-12-19 4 views
11

pandas для python опрятен. Я пытаюсь заменить список словарей на pandas-dataframe. Тем не менее, мне интересно, есть ли способ изменить значения row-by-row в for-loop так же просто?Редактировать pandas dataframe row-by-row

Вот не-панды ДИКТ-версия:

trialList = [ 
    {'no':1, 'condition':2, 'response':''}, 
    {'no':2, 'condition':1, 'response':''}, 
    {'no':3, 'condition':1, 'response':''} 
] # ... and so on 

for trial in trialList: 
    # Do something and collect response 
    trial['response'] = 'the answer!' 

... и теперь trialList содержит обновленные значения, потому что trial ссылается на это. Очень удобно! Но список-диктов очень неудобен, особенно потому, что я хотел бы вычислить материал, который по-разному использует панды.

Поэтому, учитывая trialList сверху, я, хотя я мог бы сделать это еще лучше делать что-то панд, как:

import pandas as pd  
dfTrials = pd.DataFrame(trialList) # makes a nice 3-column dataframe with 3 rows 

for trial in dfTrials.iterrows(): 
    # do something and collect response 
    trials[1]['response'] = 'the answer!' 

... но trialList остается неизменным здесь. Есть ли простой способ обновления значений по строкам, возможно, эквивалентный dict-версии? Важно, что это по очереди, так как это эксперимент, в котором участникам представлено множество испытаний, и различные данные собираются в каждом отдельном испытании.

ответ

30

Если вы действительно хотите, строка за строкой опа, вы могли бы использовать iterrows и loc:

>>> for i, trial in dfTrials.iterrows(): 
...  dfTrials.loc[i, "response"] = "answer {}".format(trial["no"]) 
...  
>>> dfTrials 
    condition no response 
0   2 1 answer 1 
1   1 2 answer 2 
2   1 3 answer 3 

[3 rows x 3 columns] 

Лучше, хотя, когда вы можете векторизации:

>>> dfTrials["response 2"] = dfTrials["condition"] + dfTrials["no"] 
>>> dfTrials 
    condition no response response 2 
0   2 1 answer 1   3 
1   1 2 answer 2   3 
2   1 3 answer 3   4 

[3 rows x 4 columns] 

И всегда apply:

>>> def f(row): 
...  return "c{}n{}".format(row["condition"], row["no"]) 
... 
>>> dfTrials["r3"] = dfTrials.apply(f, axis=1) 
>>> dfTrials 
    condition no response response 2 r3 
0   2 1 answer 1   3 c2n1 
1   1 2 answer 2   3 c1n2 
2   1 3 answer 3   4 c1n3 

[3 rows x 5 columns] 
+1

Спасибо! Верхний - это то, что мне нужно. Не так красиво/просто, как хотелось бы, но это работает. –

+0

@ Джонас указывает, что векторное решение всегда будет самым быстрым. Итерация строки за строкой ** медленная ** (и обычно ее можно избежать). –

+0

В моем случае данные обновляются пробным методом, поскольку предмет проходит эксперимент, и анализ необходимо выполнить «онлайн», прежде чем все данные будут собраны. Поэтому операции со всеми строками сразу невозможно. –