Только что протестировал код комментария @Nolan Conaway, и лучше всего это сделать:
df.groupby('amino_acid').templates.sum()
Таким образом, вы получаете информационный кадр, содержащий все, что вам нужно, и, поскольку он использует все собственные функции данных, работает быстрее и, конечно, более лаконичен, короток и чист.
Для скорости я измерил прошедшее время в кадре данных 10 ^ 4, и этот код примерно на три порядка быстрее (0,007 против 4,3 секунды), чем мой ответ ниже.
Нолан должен поместить комментарий в ответ, чтобы он мог быть зачислен его аккуратным и умным использованием pandas dataframe api.
Я оставлю здесь свой ответ на всякий случай, если кто-то найдет комментарии полезными.
Я не знаю pandas api полностью, но я не могу найти какую-либо комбинацию api, которая бы получила то, что вам нужно (но Нолан сделал!). Но кажется, что вы можете значительно улучшить свой код, не создавая список или явно архивируя данные. Если вы используете итераторы вместо этих структур, вы можете улучшить производительность.
Например, в list(zip(df.amino_acid, df.templates))
, list
не является действительно необходимым, потому что zip
уже возвращает список. Кроме того, вы можете использовать функцию izip
библиотеки itertools, которая дает итератор без построения списка. Кроме того, лучше использовать конструкторы итераторов pandas вместо вызова столбцов (что, насколько я понимаю, будет также возвращать копию данных в списке, поэтому у вас есть еще одна итерация над фреймом данных).
В любом случае, я бы попробовал что-то подобное.
sequence_counts = { }
for _, row in df.iterrows():
t, aa = row['templates'], row['amino_acid']
s = sequence_counts.get(aa, 0)
sequence_counts[aa] = s + t
Таким образом, вы действительно перебираете данные только один раз, с итератором, который дает вам фрейм данных.