Вот (не исчерпывающий) список способов сделать это в Python.Pandas, если вы знакомы с ней, - это библиотека для обработки и анализа данных.NumPy - это математическая вычислительная среда, которую интенсивно использует pandas.
A pandas.DataFrame
концептуально очень похож на лист Excel.Это очень гибкая структура сбора / данных.Давайте построим DataFrame с одним столбцом:
>>> import numpy as np
>>> import pandas as pd
>>> df = pd.DataFrame({'a': np.random.randn(10)})
>>> df
a
0 0.829202
1 -2.722945
2 0.877674
3 0.981782
4 0.398093
5 -0.593295
6 0.871504
7 0.439916
8 1.026697
9 -0.063484
Я использовал np.random.randn
для генерации последовательности случайных чисел.
Обратите внимание, что если у вас нетДоступ к сторонним библиотекам, вы также можете хранить эти данные в списке или другой встроенной коллекции.Тем не менее, Pandas - лучший инструмент для этой работы, IMO.
Пример NumPy
Давайте рассмотрим решение NumPy.Мы можем использовать numpy.where
(сокращенно np.where
), чтобы работать в основном так же, как Excel IF
, к которому вы привыкли:
>>> calc = np.where(df['a'] < 0, df['a'] ** 2, df['a'] ** 3)
>>> calc
array([5.70138715e-01, 7.41442961e+00, 6.76083380e-01, 9.46335721e-01,
6.30887662e-02, 3.51999052e-01, 6.61924036e-01, 8.51350238e-02,
1.08224773e+00, 4.03018586e-03])
Теперь мы можем назначить calc
, NumPyмассив, обратно к DataFrame df
, если нам нравится:
>>> df['calc'] = calc
>>> df
a calc
0 0.829202 0.570139
1 -2.722945 7.414430
2 0.877674 0.676083
3 0.981782 0.946336
4 0.398093 0.063089
5 -0.593295 0.351999
6 0.871504 0.661924
7 0.439916 0.085135
8 1.026697 1.082248
9 -0.063484 0.004030
Пример Pure-Python:
>>> calc = [x ** 2 if x < 0 else x ** 3 for x in df['a']]
>>> calc
[0.5701387154526354, 7.414429614316651, 0.6760833798456796, 0.9463357209355919, 0.0630887661523053, 0.3519990516487755, 0.6619240363210077, 0.08513502375096661, 1.0822477332767624, 0.004030185858203847]
>>> df['calc'] = calc
>>> df
a calc
0 0.829202 0.570139
1 -2.722945 7.414430
2 0.877674 0.676083
3 0.981782 0.946336
4 0.398093 0.063089
5 -0.593295 0.351999
6 0.871504 0.661924
7 0.439916 0.085135
8 1.026697 1.082248
9 -0.063484 0.004030
Этот пример чистого Python использует то, что обычно называют «троичным»«оператор - это x ** 2 if x < 0 else x ** 3
материал.Эта строка - просто более лаконичный, «питонский» способ сделать это:
>>> calc = []
>>> for x in df['a']:
... if x < 0:
... calc.append(x ** 2)
... else:
... calc.append(x ** 3)
...
>>> calc
[0.5701387154526354, 7.414429614316651, 0.6760833798456796, 0.9463357209355919, 0.0630887661523053, 0.3519990516487755, 0.6619240363210077, 0.08513502375096661, 1.0822477332767624, 0.004030185858203847]
Вы часто будете видеть первый подход - «понимание списка» - потому что он более лаконичен, чем последний.Однако с точки зрения вывода они эквивалентны.
Мы также можем проверить эти подходы с точки зрения синхронизации:
>>> import time
>>> N = 100000
>>>
>>> def test_numpy():
... t0 = time.time()
... for _ in range(N):
... calc = np.where(df['a'] < 0, df['a'] ** 2, df['a'] ** 3)
... t1 = time.time()
... return t1 - t0
...
>>> def test_list():
... t0 = time.time()
... for _ in range(N):
... calc = [x ** 2 if x < 0 else x ** 3 for x in df['a']]
... t1 = time.time()
... return t1 - t0
...
>>> test_numpy()
34.89216589927673
>>> test_list()
1.9015109539031982
Кажется, что подход list
немного быстрее,Если взглянуть немного глубже, используя библиотеку dis
, мы увидим, что подход np.where
имеет немного больше издержек с точки зрения выполняемых операций:
>>> import dis
>>> dis.dis("np.where(df['a'] < 0, df['a'] ** 2, df['a'] ** 3)")
1 0 LOAD_NAME 0 (np)
2 LOAD_ATTR 1 (where)
4 LOAD_NAME 2 (df)
6 LOAD_CONST 0 ('a')
8 BINARY_SUBSCR
10 LOAD_CONST 1 (0)
12 COMPARE_OP 0 (<)
14 LOAD_NAME 2 (df)
16 LOAD_CONST 0 ('a')
18 BINARY_SUBSCR
20 LOAD_CONST 2 (2)
22 BINARY_POWER
24 LOAD_NAME 2 (df)
26 LOAD_CONST 0 ('a')
28 BINARY_SUBSCR
30 LOAD_CONST 3 (3)
32 BINARY_POWER
34 CALL_FUNCTION 3
36 RETURN_VALUE
>>> dis.dis("[x ** 2 if x < 0 else x ** 3 for x in df['a']]")
1 0 LOAD_CONST 0 (<code object <listcomp> at 0x10fdcd1e0, file "<dis>", line 1>)
2 LOAD_CONST 1 ('<listcomp>')
4 MAKE_FUNCTION 0
6 LOAD_NAME 0 (df)
8 LOAD_CONST 2 ('a')
10 BINARY_SUBSCR
12 GET_ITER
14 CALL_FUNCTION 1
16 RETURN_VALUE