Сравните столбцы, перебирая строки в Python и увеличивая значение - PullRequest
0 голосов
/ 26 февраля 2020

У меня есть один кадр данных со спаренными столбцами (например, CS идет с CS_Capacity, RD идет с RD_Capacity, et c.). У меня есть столбец с месяцами, а затем одно значение, которое входит в каждый набор пар.

Я хочу сравнить CS с CS_Capacity в январе, и если CS_Capacity больше CS, я хочу увеличить CS до сделать CS = CS_Capacity, а затем уменьшить CSval на ту же сумму. Затем я хочу go до следующего месяца и делать то же самое, пока CSval = 0.

Пример данных:

data = [['2020-01-31', 3, 6, 7, 11], ['2020-02-29', 13 ,11, 8, 13], ['2020-03-31', 22, 19, 8 ,5], ['2020-04-30', 2, 3, 6, 4], ['2020-05-31', 19, 6, 4, 5], 
        ['2020-06-30', 2, 14, 6, 8], ['2020-07-31', 5, 4, 3, 6], ['2020-08-31', 5, 11, 7, 19], ['2020-09-30',2,1, 4, 5], ['2020-10-31',29, 16, 14, 10], 
        ['2020-11-30',2, 4, 6, 7], ['2020-12-31', 25, 20, 5, 3]] 

# Create the pandas DataFrame 
df = pd.DataFrame(data, columns = ['StartDate', 'RD', 'RD_Capacity', 'CS', 'CS_Capacity'], dtype=('<M8[ns]'))
df['CS_Capacity'] = df['CS_Capacity'].astype('int')
df['CS'] = df['CS'].astype('int')
df['RD_Capacity'] = df['RD_Capacity'].astype('int')
df['RD'] = df['RD'].astype('int')

CSval = 40
RDval = 22

pairs = [('CS', 'CS_Capacity', CSval), ('RD', 'RD_Capacity', RDval)]

Я работаю до l oop через варианты здесь, чтобы сделать увеличение и уменьшение:


for val1, val2, val3 in pairs:
    df['New Target' + val1] = df[val1] #create new column to store new target- set equal to val1
    df['Value' + val1 + 'Original'] = val3 # starting value incremented row by row
    for index, row in df.iterrows(): # loop through rows
        if (df[val1][index] < df[val2][index]): # for first row, if val1 is less than val2
            delta = df[val2] - df[val1] # create a delta so you know how much to decrement val3
            df['New Target' + val1]= df[val2] # set new target equal to val2
            val3 = val3 - delta # decrement val3
            df['Delta' + val1] = delta
            df['Value' + val1] = val3 # decremented value
        if (df[val1][index] > df[val2][index]): # for first row, if val2 is less than val1
            delta = df[val1] - df[val2] # create a delta so you know how much to increment val3
            df['New Target' + val1]= df[val2] # set new target equal to val2
            val3 = val3 + delta # increment val3                        
            df['Delta' + val1] = delta
            df['Value' + val1] = val3 # incremented value

Пока этот код работает, у меня есть несколько проблем:

  1. df ['Value' + val1] не соответственно увеличивать или уменьшать.
  2. Я хочу, чтобы новый val3 был перенесен на следующую строку, поэтому я могу отслеживать, как каждая строка увеличивается или уменьшается совокупно.

Итак, если CSval = 40, чтобы начать, и в январе дельта равна 3 (-), тогда df ['Value' + val1] должно равняться 37. Тогда df ['Value' + val1 + 'Original'] в следующей строке должно начинаться с 37. Поскольку следующая строка имеет дельту 2 (+), тогда df ['Value' + val1] должен быть равен 39.

Токовый выход: enter image description here

Желаемый выход: enter image description here

Где я иду не так? Я хочу, чтобы val3 увеличивался в операторах if, чтобы это работало. Что мне не хватает?

Спасибо всем!

1 Ответ

1 голос
/ 26 февраля 2020

Это кажется намного проще, чем вы делаете это. Делает ли это решение то, что вам нужно?

df['CSval'] = -(df['CS_Capacity'] - df['CS']).cumsum() + CSval
mask = (df['CSval']>=0) & (df['CS_Capacity'] > df['CS'])
df.loc[mask, 'CS'] = df.loc[mask, 'CS_Capacity']

В конце итерации значение CSVal равно 22, а кадр данных выглядит следующим образом:

0  2020-01-31   3            6  11           11   36.0
1  2020-02-29  13           11  13           13   31.0
2  2020-03-31  22           19   8            5   34.0
3  2020-04-30   2            3   6            4   36.0
4  2020-05-31  19            6   5            5   35.0
5  2020-06-30   2           14   8            8   33.0
6  2020-07-31   5            4   6            6   30.0
7  2020-08-31   5           11  19           19   18.0
8  2020-09-30   2            1   5            5   17.0
9  2020-10-31  29           16  14           10   21.0
10 2020-11-30   2            4   7            7   20.0
11 2020-12-31  25           20   5            3   22.0

Это решение создает CSVal даже когда это значение падает ниже 0, но оно изменяет значение CS только тогда, когда CSval выше нуля. Если вы хотите, вы можете очистить фрейм данных, просто выполнив следующее

...