Понимание индексации данных в pandas
Резюме: это не работает:
df[df.key==1]['D'] = 1
но это делает:
df.D[df.key==1] = 1
Зачем?
размножение:
In [1]: import pandas as pd
In [2]: from numpy.random import randn
In [4]: df = pd.DataFrame(randn(6,3),columns=list('ABC'))
In [5]: df
Out[5]:
A B C
0 1.438161 -0.210454 -1.983704
1 -0.283780 -0.371773 0.017580
2 0.552564 -0.610548 0.257276
3 1.931332 0.649179 -1.349062
4 1.656010 -1.373263 1.333079
5 0.944862 -0.657849 1.526811
In [6]: df['D']=0.0
In [7]: df['key']=3*[1]+3*[2]
In [8]: df
Out[8]:
A B C D key
0 1.438161 -0.210454 -1.983704 0 1
1 -0.283780 -0.371773 0.017580 0 1
2 0.552564 -0.610548 0.257276 0 1
3 1.931332 0.649179 -1.349062 0 2
4 1.656010 -1.373263 1.333079 0 2
5 0.944862 -0.657849 1.526811 0 2
Это не работает:
In [9]: df[df.key==1]['D'] = 1
In [10]: df
Out[10]:
A B C D key
0 1.438161 -0.210454 -1.983704 0 1
1 -0.283780 -0.371773 0.017580 0 1
2 0.552564 -0.610548 0.257276 0 1
3 1.931332 0.649179 -1.349062 0 2
4 1.656010 -1.373263 1.333079 0 2
5 0.944862 -0.657849 1.526811 0 2
но это делает:
In [11]: df.D[df.key==1] = 3.4
In [12]: df
Out[12]:
A B C D key
0 1.438161 -0.210454 -1.983704 3.4 1
1 -0.283780 -0.371773 0.017580 3.4 1
2 0.552564 -0.610548 0.257276 3.4 1
3 1.931332 0.649179 -1.349062 0.0 2
4 1.656010 -1.373263 1.333079 0.0 2
5 0.944862 -0.657849 1.526811 0.0 2
Мой вопрос: почему работает только 2-й способ? Кажется, я не вижу разницы в логике выбора / индексации?
Версия 0.10.0
Изменить: это не должно быть сделано, как это больше. С 0.11 есть .loc
смотрите здесь: http://pandas.pydata.org/pandas-docs/stable/indexing.html
2 ответа
Документация панд гласит:
Возвращение вида вместо копии
Правила о том, когда возвращается представление данных, полностью зависят от NumPy. Когда в операции индексации участвует массив меток или логический вектор, результатом будет копия. При индексировании и разрезании по одной метке / скаляру, например, df.ix[3:6] или df.ix[:, 'A'], будет возвращено представление.
В df[df.key==1]['D']
сначала вы выполняете логическое нарезание (приводящее к копии Dataframe), затем выбираете столбец ['D'].
В df.D[df.key==1] = 3.4
Сначала вы выбираете столбец, а затем выполняете логическое нарезание результирующей серии.
Это, кажется, имеет значение, хотя я должен признать, что это немного нелогично.
Изменить: Различие было выявлено Дугалом, см. Его комментарий: С версией 1 копия сделана как __getitem__
Метод вызывается для логического среза. Для версии 2 только __setitem__
доступ к методу - таким образом, не возвращая копию, а просто присваивая.
Я почти уверен, что ваш первый способ - это возвращение копии, а не представления, и поэтому присвоение ей не изменяет исходные данные. Я не уверен, почему это происходит, хотя.
Похоже, это связано с порядком, в котором вы выбираете строки и столбцы, а НЕ с синтаксисом получения столбцов. Они оба работают:
df.D[df.key == 1] = 1
df['D'][df.key == 1] = 1
И ни одна из этих работ:
df[df.key == 1]['D'] = 1
df[df.key == 1].D = 1
Из этого доказательства я бы предположил, что срез df[df.key == 1]
возвращает копию. Но это не так! df[df.key == 1] = 0
фактически изменит исходные данные, как если бы это был вид.
Так что я не уверен. Я чувствую, что это поведение изменилось с версией панд. Кажется, я помню, что df.D использовал для возврата копии, а df['D'] использовал для возврата представления, но это больше не соответствует действительности (pandas 0.10.0).
Если вы хотите получить более полный ответ, отправьте сообщение на форуме pystatsmodels: https://groups.google.com/forum/?fromgroups