Я изучаю итерацию и применяю функцию в пандах. У меня есть пример ниже. для каждых 4 строк примените функцию (1-я строка + 0, 2-я строка + 0, 3-я строка = 0, 4-я строка = 0) и так далее. Есть ли ссылки на ресурсы для выполнения этой операции? Большое спасибо.
data = {'DATE': ['2023-12-29', '2023-12-29', '2023-12-29', '2023-12-29','2024-01-31','2024-01-31','2024-01-31','2024-01-31',
'2024-02-27','2024-02-27','2024-02-27','2024-02-27'],
'score': [10, 5, 30, 41,12,7,32,43,14,9,34,45]}
df = pd.DataFrame(data=data)
DATE Score Result
0 2023-12-29 10 10
1 2023-12-29 5 5
2 2023-12-29 30 0
3 2023-12-29 41 0
4 2024-01-31 12 12
5 2024-01-31 7 7
6 2024-01-31 32 0
7 2024-01-31 43 0
8 2024-02-27 14 14
9 2024-02-27 9 9
10 2024-02-27 34 0
11 2024-02-27 45 0
Код
cond = df.index.to_series().mod(4).isin([2, 3])
df['result'] = df['score'].mask(cond, 0)
дф
DATE score result
0 2023-12-29 10 10
1 2023-12-29 5 5
2 2023-12-29 8 0
3 2023-12-29 2 0
4 2023-12-29 7 7
5 2023-12-27 10 10
6 2023-12-27 12 0
7 2023-12-27 7 0
8 2023-12-27 9 9
9 2024-01-31 13 13
10 2024-02-27 14 0
11 2024-02-27 9 0
Обновить ответ на дополнительный вопрос
(1-я строка +5, 2-я строка +8, 3-я строка = 0, 4-я строка -10)
s = pd.Series([5, 8, 0, -10])[df.index % 4].reset_index(drop=True)
df['result'] = df['score'] + s
дф
DATE score result
0 2023-12-29 10 15
1 2023-12-29 5 13
2 2023-12-29 8 8
3 2023-12-29 2 -8
4 2023-12-29 7 12
5 2023-12-27 10 18
6 2023-12-27 12 12
7 2023-12-27 7 -3
8 2023-12-27 9 14
9 2024-01-31 13 21
10 2024-02-27 14 14
11 2024-02-27 9 -1
Индексировать массив numpy проще, но вы, возможно, не знаете numpy, поэтому я выполнил индексацию в серии pandas.
numpy.select может сослужить вам хорошую службу:
import numpy as np
n = 4
index_n = df.index.to_series().mod(n)
conditions = [
index_n.eq(i)
for i in range(n)
]
choices = [
df.score.add(5), # 1st row +5
df.score.add(8), # 2nd row +8
0, # 3rd row = 0
df.score.sub(10), # 4th row -10
]
df["result"] = np.select(conditions, choices)
Выход:
DATE score result
0 2023-12-29 10 15
1 2023-12-29 5 13
2 2023-12-29 30 0
3 2023-12-29 41 31
4 2024-01-31 12 17
5 2024-01-31 7 15
6 2024-01-31 32 0
7 2024-01-31 43 33
8 2024-02-27 14 19
9 2024-02-27 9 17
10 2024-02-27 34 0
11 2024-02-27 45 35
Если каждые 4 строки расположены по столбцу DATE
, можно использовать GroupBy.transform со специальной функцией:
def f(x):
x.iat[0] += 5
x.iat[1] += 8
x.iat[2] = 0
x.iat[3] -= 10
return x
df['result'] = df.groupby('DATE')['score'].transform(f)
print (df)
DATE score result
0 2023-12-29 10 15
1 2023-12-29 5 13
2 2023-12-29 30 0
3 2023-12-29 41 31
4 2024-01-31 12 17
5 2024-01-31 7 15
6 2024-01-31 32 0
7 2024-01-31 43 33
8 2024-02-27 14 19
9 2024-02-27 9 17
10 2024-02-27 34 0
11 2024-02-27 45 35
Если каждые 4 строки не соответствуют столбцу DATE
:
def f(x):
x.iat[0] += 5
x.iat[1] += 8
x.iat[2] = 0
x.iat[3] -= 10
return x
df['result'] = df.groupby(np.arange(len(df.index)) // 4)['score'].transform(f)
Если возможно, в какой-то группе есть 1,2 или 3 строки, одна идея — пропустить эту строку, например. автор try-except
:
df = pd.DataFrame(data=data).drop(11)
def f(x):
try:
x.iat[0] += 5
x.iat[1] += 8
x.iat[2] = 0
x.iat[3] -= 10
except IndexError:
pass
return x
df['result'] = df.groupby(np.arange(len(df.index)) // 4)['score'].transform(f)
print (df)
DATE score result
0 2023-12-29 10 15
1 2023-12-29 5 13
2 2023-12-29 30 0
3 2023-12-29 41 31
4 2024-01-31 12 17
5 2024-01-31 7 15
6 2024-01-31 32 0
7 2024-01-31 43 33
8 2024-02-27 14 19
9 2024-02-27 9 17
10 2024-02-27 34 0
Для эффективного подхода не зацикливайтесь, создавайте массивы numpy с помощью numpy.tile, добавляйте значения и умножайте на 1/0 строки, которые вы хотите сохранить/сбросить:
import numpy as np
add = [5, 8, 0, -10] # value to add
mul = [1, 1, 0, 1] # values to reset (0 = reset)
n = int(np.ceil(len(df)/len(add))) # 3
df['Result'] = (df['score']
.mul(np.tile(mul, n)[:len(df)])
.add(np.tile(add, n)[:len(df)])
)
Примечание. если количество строк всегда кратно количеству операций, вы можете использовать n = len(df)//len(add)
и удалить [:len(df)]
.
n = len(df)//len(add) # 3
df['Result'] = df['score'].mul(np.tile(mul, n)).add(np.tile(add, n))
Выход:
DATE score Result
0 2023-12-29 10 15
1 2023-12-29 5 13
2 2023-12-29 30 0
3 2023-12-29 41 31
4 2024-01-31 12 17
5 2024-01-31 7 15
6 2024-01-31 32 0
7 2024-01-31 43 33
8 2024-02-27 14 19
9 2024-02-27 9 17
10 2024-02-27 34 0
11 2024-02-27 45 35
Если ваши группы нерегулярны, вы можете объединить это с groupby.cumcount и индексацией numpy:
add = np.array([5, 8, 0, -10])
mul = np.array([1, 1, 0, 1])
n = df.groupby('DATE').cumcount()
df['Result'] = df['score'].mul(mul[n]).add(add[n])