Преимущество использования pandas
заключается в том, что вы можете выполнять операции по столбцам. Они , как правило, более эффективны, чем итерирование по DataFrame с параметром для l oop.
. Я немного изменил ваш df
, чтобы показать вам эффект отфильтровывания нужных нам строк .
>>> import pandas as pd
>>> from scipy.stats import ttest_ind
>>> GOIlist = ["GeneA","GeneB"]
>>> rnatest = {'Gene symbol':["GeneA","GeneB", "GeneC"],"rnaseq1A":[1,1.5,2],"rnaseq1B":[1.3,1.2,1.1],"rnaseq2A":[2.3,2.7,3.1],"rnaseq2B":[2,2.6,3.2]}
>>> df = pd.DataFrame(rnatest)
>>> print(df)
Gene symbol rnaseq1A rnaseq1B rnaseq2A rnaseq2B
0 GeneA 1.0 1.3 2.3 2.0
1 GeneB 1.5 1.2 2.7 2.6
2 GeneC 2.0 1.1 3.1 3.2
Теперь, как бы я переписал ваш код:
- Используйте
set_index
, чтобы сделать строку Gene symbol
индексом, это ускоряет время поиска (особенно если у вас большие фреймы данных) - Используйте
loc
для фильтрации строк с символом гена в GOIlist
- Создайте два новых столбца
pVal
и tVal
, для которых Вы назначаете выход ttest_ind
. Обратите внимание, что нам больше не нужно перебирать строки. - Опционально, удалите столбцы
rnaseq*
, если вы не хотите видеть их в своих выходных данных.
В коде:
>>> df3 = df.set_index(['Gene symbol'])
>>> df3 = df3.loc[GOIlist]
>>> df3['tVal'], df3['pVal'] = ttest_ind([df3["rnaseq1A"], df3["rnaseq1B"]], [df3["rnaseq2A"], df3["rnaseq2B"]])
>>> df3 = df3.drop(['rnaseq1A', 'rnaseq1B', 'rnaseq2A', 'rnaseq2B'], axis=1)
>>> print(df3)
tVal pVal
Gene symbol
GeneA -4.714045 0.042174
GeneB -8.221922 0.014473
Итак, насколько эффективнее теперь этот код?
Если я искусственно увеличу размер нашего DataFrame в 10.000 раз (то есть всего 30.000 строк вместо 3)
n = 10_000
rnatest = {'Gene symbol':["GeneA","GeneB", "GeneC"]*n, "rnaseq1A":[1,1.5,2]*n, "rnaseq1B":[1.3,1.2,1.1]*n, "rnaseq2A":[2.3,2.7,3.1]*n, "rnaseq2B":[2,2.6,3.2]*n}
df = pd.DataFrame(rnatest)
тогда я могу использовать timeit
для измерения времени выполнения кода. Для вашего первоначального подхода я получаю результат:
13.7 s ± 555 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
, в то время как мой подход заканчивается в
45.2 ms ± 1.27 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
, так что * более чем в 300 раз ускорение!