#python #pandas #dataframe
#python #pandas #фрейм данных
Вопрос:
У меня есть этот фрейм данных pandas
interval_mins = {
'10' : 0.11,
'15' : 0.4,
'20' : 0.19
}
pd.DataFrame({
'id' : [10, 15, 20, 10, 20, 15],
'interval' : [0.1, 0.39, 0.2, 0.12, 0.25, 0.42]
})
В pandas DataFrame я хочу выбрать элементы со interval
значениями, меньшими, чем interval_mins
для каждого id
, а затем добавить к следующему interval
тому же значению id
.
Есть ли способ без использования for
?
Ожидаемый результат:
pd.DataFrame({
'id' : [10, 15, 20, 10, 20, 15],
'interval' : [0.1, 0.39, 0.2, 0.22, 0.25, 0.81]
})
Комментарии:
1. неясно (элементы меньше интервала минут?) относительно того, что требуется, пожалуйста, вставьте ожидаемый результат
2. Я не думаю, что ваш пример (на изображении) соответствует вашему правилу, для id = 20 вы также должны добавить, поскольку 0.22> 0.2?
Ответ №1:
Давайте сделаем:
m = df['interval'] < df['id'].astype(str).map(interval_mins)
df.loc[m.groupby(df['id']).shift(fill_value=False), 'interval'] = df.groupby('id')['interval'].shift()
Подробные сведения:
Создайте логическую маску, представляющую условие, в котором interval
значения меньше, чем interval_mins
для каждого id
:
print(m)
0 True
1 True
2 False
3 False
4 False
5 False
dtype: bool
groupby
логическая маска m
включается id
и shift
выключается:
print(m.groupby(df['id']).shift(fill_value=False))
0 False
1 False
2 False
3 True
4 False
5 True
dtype: bool
groupby
фрейм данных и столбец id
shift
interval
:
print(df.groupby('id')['interval'].shift())
0 NaN
1 NaN
2 NaN
3 0.10
4 0.20
5 0.39
Name: interval, dtype: float64
Используйте логическую индексацию с loc
помощью, чтобы добавить значения, соответствующие сдвинутой маске:
print(df)
id interval
0 10 0.10
1 15 0.39
2 20 0.20
3 10 0.22
4 20 0.25
5 15 0.81
Ответ №2:
В соответствии с вашим правилом, но не с вашим выводом (см. Мой комментарий), это должно сработать. Я оставляю промежуточные вычисления на месте, чтобы было легче понять, что происходит. Обратите внимание, что я заменил ключи на interval_mis
int
s из str
s. Желаемый результат в столбце interval_2
df['add'] = df['id'].map(interval_mins)
df['add_cond'] = df['add']*(df['add'] > df['interval'])
df = (df.groupby('id')
.apply(lambda d: d.assign(add_cond_shift=d['add_cond'].shift()))
.fillna(0)
.reset_index(drop = True)
)
df['interval_2'] = df['interval'] df['add_cond_shift']
df
выдает
id interval add add_cond add_cond_shift interval_2
0 10 0.10 0.11 0.11 0.00 0.10
1 10 0.12 0.11 0.00 0.11 0.23
2 15 0.39 0.40 0.40 0.00 0.39
3 15 0.42 0.40 0.00 0.40 0.82
4 20 0.20 0.22 0.22 0.00 0.20
5 20 0.25 0.22 0.00 0.22 0.47