Как создать новый столбец в фрейме данных, который будет функцией другого столбца и обусловлен быстрее, чем цикл for? - PullRequest
1 голос
/ 18 апреля 2019

У меня относительно большой фрейм данных (8737 строк и 16 столбцов всех типов переменных, строк, целых чисел, логических значений и т. Д.), И я хочу создать новый столбец на основе уравнения и некоторых условий. По сути, я хочу перебрать один конкретный столбец, взять его значения и после операции вычислить значение. Затем мне нужно проверить, удовлетворяет ли это значение некоторым условиям (> = или <до ​​заданного значения). Если он удовлетворяет условию, тогда мне нужно сохранить результат вычисления в качестве элемента нового столбца, в противном случае присвоить этому элементу фиксированное значение. </p>

Я делаю это, зацикливая весь набор данных с помощью цикла for, который занимает огромное количество времени. Я новичок в python и не могу найти аналогичного решения проблемы в сети, кроме чередования существующих столбцов без цикла for.

Для простоты скажем, у меня есть этот фрейм данных с именем df:

df=pd.DataFrame()
df['A']=[5,3,7,4,3,0,1,7,8,10,9,4,3,2,0]
df['S']=np.nan
df['S'][0]=5

Out[4]: 
     A    S
0    5  5.0
1    3  NaN
2    7  NaN
3    4  NaN
4    3  NaN
5    0  NaN
6    1  NaN
7    7  NaN
8    8  NaN
9   10  NaN
10   9  NaN
11   4  NaN
12   3  NaN
13   2  NaN
14   0  NaN

где S - новый столбец, который мне нужно вычислить, начиная с заданного значения. Следующим значением S мне должно быть предыдущее значение S плюс некоторый расчет. В основном, для каждого шага вычисления я хочу S (i) = S (i-1) + A (i) x0,5-2 * и сразу после этого проверять если S (i) = <5, то S (i) = 5, в противном случае S (i)> = 10, тогда S (i) = 10 . Это один шаг иттерации. Мой код с желаемым результатом:

for i in range (1,df.shape[0]):
    df.S[i]=df.S[i-1]+df.A[i]*0.5-2
    if df.S[i]<=5:
        df.S[i]=5
    elif df.S[i]>10:
        df.S[i]=10
df

Out[6]: 
     A     S
0    5   5.0
1    3   5.0
2    7   6.5
3    4   6.5
4    3   6.0
5    0   5.0
6    1   5.0
7    7   6.5
8    8   8.5
9   10  10.0
10   9  10.0
11   4  10.0
12   3   9.5
13   2   8.5
14   0   6.5

Этот код для 8737 строк занимает около 20 минут. Есть ли способ сделать это без цикла for или с другим, более быстрым итеративным методом? Если вам нужны какие-либо разъяснения, пожалуйста, спросите меня. Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 18 апреля 2019

Не уверен, если это то, что вы ищете.Я думаю, что вы можете использовать .apply для этого случая.Например:

df=pd.DataFrame()
df['A']=[5,3,7,4,3,0,1,7,8,10,9,4,3,2,0]
df['S']=np.nan
df['S'][0]=5

def cal(i):
    return i**2

df['S'] = df['A'].apply(cal)

display(df)

Он назначит новые значения для 'S' на основе расчета

0 голосов
/ 18 апреля 2019

Вы можете попробовать numba для его оптимизации:

from numba import jit
@jit(nopython=True)
def get_vals(a, first):
    out = np.zeros(a.shape[0], dtype=float)
    out[0] = first
    for i in range(1, a.shape[0]):
        out[i] = out[i-1] + a[i]*0.5-2
        out[i] = 5 if out[i]<=5 else out[i]
        out[i] = 10 if out[i] > 10 else out[i]
    return out

arr = df['A'].values
df['new'] = get_vals(arr, df.loc[0, 'S'])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...