У меня есть такой кадр данных:
import pandas as pd
df = pd.DataFrame({
"time": [1, 2, 1, 2],
"site": ['a', 'a', 'b', 'b'],
"val1": [11, 12, 21, 22],
"val2": [101, 102, 201, 202]
})
df.set_index(['time', 'site'], inplace=True, append=False)
df = df.unstack("site")
print df
val1 val2
site a b a b
time
1 11 21 101 201
2 12 22 102 202
Я хотел бы изменить некоторые значения, соответствующие логическому фильтру. например.:
ix = df.val1 > 20
print ix
site a b
time
1 False True
2 False True
Естественно было бы попробовать df.val1[ix] = 50
. Это выполняет ожидаемое назначение, но выдает предупреждение: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead
.
Итак, теперь я пытаюсь добиться чего-то подобного, используя df.loc
. Но я не могу найти способ использовать df.loc
с такой логической маской. Кажется, это потому, что я использую иерархические столбцы, т. е. у меня нет особых проблем, если у меня есть только один набор значений (val1). К сожалению, назначения с логическими фильтрами для иерархических столбцов не очень хорошо описаны в документы.
Я пытался сослаться на df.loc[:,'val1',ix]
, но это дает IndexingError: Too many indexers
. Я пробовал df.loc[:,'val1'][ix] = 50
, и это работает, но дает SettingWithCopyWarning
.
Я могу использовать df.val1 = df.val1.where(~ix, other=50)
, но это кажется неинтуитивным, неэффективным и негибким (например, его нельзя легко расширить, чтобы добавить 10 к существующим значениям).
Есть ли какой-то другой метод индексации, который я должен использовать для присвоения значений иерархическому столбцу фрейма данных на основе логической маски?
Отредактировано для расширения вопроса:
Я не осознавал, что это будет проблемой, но на самом деле я хотел бы фильтровать значения в столбцах val1
и val2
и изменять значения в обоих наборах столбцов, примерно так:
ix = (df.val1 > 20) | (df.val2 < 102)
df.val1[ix] = 50
df.val2[ix] = 150
Есть ли простой подход к индексации, который может это сделать? Это довольно просто с numpy ndarrays, но с кадром данных pandas, кажется, все сложнее.