Подтвердить что ты не робот

Понимание 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

Ссылка на блокнот

Мой вопрос: почему работает только второй способ? Кажется, я не вижу разницы в логике выбора/индексации?

Версия 0.10.0

Изменить: этого больше не должно быть сделано. Начиная с 0.11 существует .loc, см. Здесь: http://pandas.pydata.org/pandas-docs/stable/indexing.html

4b9b3361

Ответ 1

Документация pandas гласит:

Возврат представления к копии

Правила о том, когда возвращается представление данных, полностью зависит от 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__ - таким образом, не возвращается копия, а просто назначается.

Ответ 2

Я уверен, что ваш первый способ возвращает копию вместо представления, и поэтому присвоение ей не изменяет исходные данные. Я не уверен, почему это происходит.

Кажется, это связано с порядком, в котором вы выбираете строки и столбцы, а не синтаксис для получения столбцов. Эти обе работают:

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 фактически изменит исходные данные, как если бы это был вид.

Итак, я не уверен. Я считаю, что это изменение изменилось с версией pandas. Кажется, я помню, что df.D использовался для возврата копии и df ['D'], используемых для возврата представления, но это больше не выглядит истинным (pandas 0.10.0).

Если вам нужен более полный ответ, вы должны опубликовать его на форуме pystatsmodels: https://groups.google.com/forum/?fromgroups#!forum/pystatsmodels