Я пытаюсь написать вложенный оператор if/else, используя панд, но не очень хорошо, если операторы в пандах. Пожалуйста, найдите образец данных CSV, который обрабатывается, и пример кода, который я написал до сих пор.

df:

t1  
8
1134
0
119
122
446
21
0
138 
0

Текущая логика оператора if / else:

import pandas as pd

df = pd.read_csv('file.csv', sep=';')

def get_cost(df):
    t_zone = 720
    max_rate = 5.5
    rate = 0.0208
    duration = df['t1']

    if duration < t_zone:
        if(duration * rate) >= max_rate:
            return max_rate
        else:
            return(duration * rate)
    else:
        if duration >= 720:
            x = int(duration/720)
            y = ((duration%720) * rate)
            if y >= max_rate:
                return((x * max_rate) + max_rate)
            else:
                return((x * max_rate) + y)

cost = get_cost(df)

Этот фрагмент кода вызывает ошибку ValueError: The truth value of a Series is ambiguous. Если у кого-то есть лучшие решения или он может помочь перевести это выражение if / else в более пандский способ, это было бы удивительно!

1
mm_nieder 21 Авг 2018 в 17:41

3 ответа

Лучший ответ

Попробуйте это решение.

import pandas as pd

df = pd.read_csv('file.csv')

def get_cost(x):
    t_zone = 720
    max_rate = 5.5
    rate = 0.0208
    duration = x['t1']
    if duration < t_zone:
        if(duration * rate) >= max_rate:
            return max_rate
        else:
            return(duration * rate)
    else:
        if duration >= 720:
            x = int(duration/720)
            y = ((duration%720) * rate)
            if y >= max_rate:
                return((x * max_rate) + max_rate)
            else:
                return((x * max_rate) + y)

df['cost'] = df.apply(get_cost, axis=1)

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

Вывод:

    t1  cost
0   8   0.1664
1   1134    11.0000
2   0   0.0000
3   119 2.4752
4   122 2.5376
5   446 5.5000
6   21  0.4368
7   0   0.0000
8   138 2.8704
9   0   0.0000
2
V Sree Harissh 21 Авг 2018 в 14:56

Вы должны выполнять итерацию по продолжительности, а не сравнивать ее напрямую с числом. Вы могли бы сделать это.

import pandas as pd

df = pd.read_csv('file.csv', sep=';')

def get_cost(df):
    t_zone = 720
    max_rate = 5.5
    rate = 0.0208
    duration = df['t1']
    ratecol = []
    for i in duration:
        if i < t_zone:
            if(i * rate) >= max_rate:
                ratecol.append(max_rate)
            else:
                ratecol.append(i * rate)
        else:
            if i >= 720:
                x = int(i/720)
                y = ((i%720) * rate)
                if y >= max_rate:
                    ratecol.append((x * max_rate) + max_rate)
                else:
                    ratecol.append((x * max_rate) + y)
    return ratecol
df['cost'] = get_cost(df)

Этот код дает точно такой же результат, как и тот, который был опубликован ранее.

1
Interested_Programmer 21 Авг 2018 в 15:01

Неэффективно использовать циклы и if операторы в пандах, если это не является абсолютно необходимым. Вот полностью векторизованное, 100% решение для панд:

import numpy as np # Needs numpy, too
x = df['t1'] // 720 * max_rate # Note the use of //!
y = df['t1'] %  720 * rate
df['cost'] = np.where(df['t1'] < t_zone, 
                      np.minimum(df['t1'] * rate, max_rate),
                      np.minimum(y,               max_rate) + x)
4
DYZ 21 Авг 2018 в 15:12
51951181