Изменения значения панд / Numpy группы и изменения производной стоимости выше / ниже 0 - PullRequest
0 голосов
/ 30 октября 2018

У меня есть ряд значений (Pandas DF или Numpy Arr):

vals = [0,1,3,4,5,5,4,2,1,0,-1,-2,-3,-2,3,5,8,4,2,0,-1,-3,-8,-20,-10,-5,-2,-1,0,1,2,3,5,6,8,4,3]
df = pd.DataFrame({'val': vals})

Я хочу классифицировать / сгруппировать значения по 4 категориям:

  1. Увеличение выше 0
  2. Снижение выше 0
  3. Увеличение ниже 0
  4. Уменьшение ниже 0

Текущий подход с Pandas состоит в том, чтобы классифицировать на выше / ниже 0, а затем на увеличение / уменьшение, наблюдая, как значения diff меняются выше / ниже 0.

df['above_zero'] = np.where(df['val'] >= 0, 1, 0)
df['below_zero'] = np.where(df['val'] < 0, 1, 0)
df['diffs'] = df['val'].diff()
df['diff_above_zero'] = np.where(df['diffs'] >= 0, 1, 0)
df['diff_below_zero'] = np.where(df['diffs'] < 0, 1, 0)

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

Желаемый результат будет выглядеть следующим образом (* col группы набирается вручную, могут быть ошибки в вычисленных значениях):

id   val  above_zero  below_zero  diffs  diff_above_zero  diff_below_zero  group
0     0           1           0    0.0                1                0      0
1     1           1           0    1.0                1                0      0
2     3           1           0    2.0                1                0      0
3     4           1           0    1.0                1                0      0
4     5           1           0    1.0                1                0      0
5     5           1           0    0.0                1                0      0
6     4           1           0   -1.0                0                1      1
7     2           1           0   -2.0                0                1      1
8     1           1           0   -1.0                0                1      1
9     0           1           0   -1.0                0                1      1
10   -1           0           1   -1.0                0                1      2
11   -2           0           1   -1.0                0                1      2
12   -3           0           1   -1.0                0                1      2
13   -2           0           1    1.0                1                0      3
14    3           1           0    5.0                1                0      4
15    5           1           0    2.0                1                0      4
16    8           1           0    3.0                1                0      4
17    4           1           0   -4.0                0                1      5
18    2           1           0   -2.0                0                1      5
19    0           1           0   -2.0                0                1      5
20   -1           0           1   -1.0                0                1      6
21   -3           0           1   -2.0                0                1      6
22   -8           0           1   -5.0                0                1      6
23  -20           0           1  -12.0                0                1      6
24  -10           0           1   10.0                1                0      7
25   -5           0           1    5.0                1                0      7
26   -2           0           1    3.0                1                0      7
27   -1           0           1    1.0                1                0      7
28    0           1           0    1.0                1                0      8
29    1           1           0    1.0                1                0      8
30    2           1           0    1.0                1                0      8
31    3           1           0    1.0                1                0      8
32    5           1           0    2.0                1                0      8
33    6           1           0    1.0                1                0      8
34    8           1           0    2.0                1                0      8
35    4           1           0   -4.0                0                1      9
36    3           1           0   -1.0                0                1      9

Буду признателен за любую помощь, как решить это эффективно. Спасибо!

Ответы [ 2 ]

0 голосов
/ 30 октября 2018

Следующий код создаст два столбца: c1 и c2.

Значения c1 соответствуют следующим 4 категориям:

  • 0 означает минус и увеличение
  • 1 означает выше нуля и увеличивается
  • 2 означает минус и убывает
  • 3 означает выше нуля и убывает

И c2 соответствует номеру восходящей группы, как только условие (то есть c1) изменяется (как вы хотели). Кредиты @ user3483203 для использования shift с cumsum

# calculate difference
df["diff"] = df['val'].diff()
# set first value in column 'diff' to 0 (as previous step sets it to NaN)
df.loc[0, 'diff'] = 0
df["c1"] = (df['val'] >= 0).astype(int) + (df["diff"] < 0).astype(int) * 2
df["c2"] = (df["c1"] != df["c1"].shift().fillna(df["c1"])).astype(int).cumsum()

Результат:

    val  diff  c1  c2
0     0   0.0   1   0
1     1   1.0   1   0
2     3   2.0   1   0
3     4   1.0   1   0
4     5   1.0   1   0
5     5   0.0   1   0
6     4  -1.0   3   1
7     2  -2.0   3   1
8     1  -1.0   3   1
9     0  -1.0   3   1
10   -1  -1.0   2   2
11   -2  -1.0   2   2
12   -3  -1.0   2   2
13   -2   1.0   0   3
14    3   5.0   1   4
15    5   2.0   1   4
16    8   3.0   1   4
17    4  -4.0   3   5
18    2  -2.0   3   5
19    0  -2.0   3   5
20   -1  -1.0   2   6
21   -3  -2.0   2   6
22   -8  -5.0   2   6
23  -20 -12.0   2   6
24  -10  10.0   0   7
25   -5   5.0   0   7
26   -2   3.0   0   7
27   -1   1.0   0   7
28    0   1.0   1   8
29    1   1.0   1   8
30    2   1.0   1   8
31    3   1.0   1   8
32    5   2.0   1   8
33    6   1.0   1   8
34    8   2.0   1   8
35    4  -4.0   3   9
36    3  -1.0   3   9
0 голосов
/ 30 октября 2018

Настройка

g1 = ['above_zero', 'below_zero', 'diff_above_zero', 'diff_below_zero']

Вы можете просто проиндексировать все свои логические столбцы и использовать shift:

c = df.loc[:, g1]
(c != c.shift().fillna(c)).any(1).cumsum()

0     0
1     0
2     0
3     0
4     0
5     0
6     1
7     1
8     1
9     1
10    2
11    2
12    2
13    3
14    4
15    4
16    4
17    5
18    5
19    5
20    6
21    6
22    6
23    6
24    7
25    7
26    7
27    7
28    8
29    8
30    8
31    8
32    8
33    8
34    8
35    9
36    9
dtype: int32
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...