«Конечно, до тех пор, пока вы выделяете память в куче», - где выделенная память не имеет к этому никакого отношения. Это все о семантике. Возьмем, например:
Derived d;
Base* b = &d;
d
находится в стеке (автоматическая память), но полиморфизм будет по-прежнему работать на b
.
Если у вас нет указатель базового класса или ссылка на производный класс, полиморфизм не работает, потому что у вас больше нет производного класса. Take
Base c = Derived();
Объект c
не является Derived
, а Base
из-за нарезки. Итак, технически, полиморфизм все еще работает, просто у вас больше нет объекта Derived
.
Теперь возьмите
Base* c = new Derived();
c
, просто указывая на некоторые место в памяти, и вам все равно, действительно ли это Base
или Derived
, но вызов метода virtual
будет разрешен динамически.
Примечание: в версии pandas 0.20.0 и выше ix
является устаревшим , и вместо этого рекомендуется использовать loc
и iloc
. Я оставил части этого ответа, которые описывают ix
в качестве ссылки для пользователей более ранних версий панд. Примеры были добавлены ниже, показывая альтернативы ix
.
Сначала рассмотрим три метода:
loc
получает строки (или столбцы) с конкретными метками из индекса. iloc
получает строки (или столбцы) в определенных положениях в индексе (поэтому он принимает только целые числа). ix
обычно пытается например, loc
, но возвращается к тому, чтобы вести себя как iloc
, если метка отсутствует в индексе. Важно отметить некоторые тонкости, которые могут сделать ix
немного сложнее use:
ix
будет использовать индексирование на основе меток и не возвращаться к индексированию на основе позиции. Если метка не указана в индексе, возникает ошибка. ix
немедленно будет использовать позицию- а не индексации на основе меток. Если, однако, ix
задан другой тип (например, строка), он может использовать индексирование на основе меток. Чтобы проиллюстрировать различия между тремя методами, рассмотрим следующую серию :
>>> s = pd.Series(np.nan, index=[49,48,47,46,45, 1, 2, 3, 4, 5])
>>> s
49 NaN
48 NaN
47 NaN
46 NaN
45 NaN
1 NaN
2 NaN
3 NaN
4 NaN
5 NaN
Мы рассмотрим срез с целым значением 3
.
В этом случае s.iloc[:3]
возвращает нам первые 3 строки (так как он обрабатывает 3 как позиция), а s.loc[:3]
возвращает нам первые 8 строк (так как он рассматривает 3 как метку):
>>> s.iloc[:3] # slice the first three rows
49 NaN
48 NaN
47 NaN
>>> s.loc[:3] # slice up to and including label 3
49 NaN
48 NaN
47 NaN
46 NaN
45 NaN
1 NaN
2 NaN
3 NaN
>>> s.ix[:3] # the integer is in the index so s.ix[:3] works like loc
49 NaN
48 NaN
47 NaN
46 NaN
45 NaN
1 NaN
2 NaN
3 NaN
Уведомление s.ix[:3]
возвращает ту же серию, что и s.loc[:3]
, поскольку она ищет метка сначала, а не работа над позицией (и индекс для s
имеет целочисленный тип).
Что делать, если мы попытаемся использовать целую метку, которая не находится в индексе (скажем, 6
)?
Здесь s.iloc[:6]
возвращает первые 6 строк Серии, как ожидалось. Однако s.loc[:6]
вызывает KeyError, поскольку 6
не находится в индексе.
>>> s.iloc[:6]
49 NaN
48 NaN
47 NaN
46 NaN
45 NaN
1 NaN
>>> s.loc[:6]
KeyError: 6
>>> s.ix[:6]
KeyError: 6
В соответствии с отмеченными выше тонкостями s.ix[:6]
теперь вызывает KeyError, потому что он пытается работать как loc
, но не может найти 6
в индексе. Поскольку наш индекс имеет целочисленный тип ix
, он не возвращается к поведению, как iloc
.
Если, однако, наш индекс был смешанного типа, то целое число ix
будет вести себя как iloc
немедленно, вместо того, чтобы поднимать KeyError:
>>> s2 = pd.Series(np.nan, index=['a','b','c','d','e', 1, 2, 3, 4, 5])
>>> s2.index.is_mixed() # index is mix of different types
True
>>> s2.ix[:6] # now behaves like iloc given integer
a NaN
b NaN
c NaN
d NaN
e NaN
1 NaN
Имейте в виду, что ix
все еще могут принимать нецелые числа и вести себя как loc
:
>>> s2.ix[:'c'] # behaves like loc given non-integer
a NaN
b NaN
c NaN
As общие рекомендации, если вы используете только индексирование с использованием меток или только индексирование с использованием целых позиций, придерживайтесь loc
или iloc
, чтобы избежать неожиданных результатов. Не пытайтесь использовать ix
.
Иногда, учитывая DataFrame, вы хотите использовать методы меток меток и позиционных индексов для строк и столбцов.
Например, рассмотрим следующие DataFrame. Как лучше всего разрезать строки до и включая «c» и взять первые четыре столбца?
>>> df = pd.DataFrame(np.nan,
index=list('abcde'),
columns=['x','y','z', 8, 9])
>>> df
x y z 8 9
a NaN NaN NaN NaN NaN
b NaN NaN NaN NaN NaN
c NaN NaN NaN NaN NaN
d NaN NaN NaN NaN NaN
e NaN NaN NaN NaN NaN
В более ранних версиях панд (до 0.20.0) ix
позволяет сделать это довольно аккуратно - мы можем нарезать строки по метке и столбцам по положению (обратите внимание, что для столбцов ix
по умолчанию будет использоваться резка на основе положения, поскольку 4
не является именем столбца):
>>> df.ix[:'c', :4]
x y z 8
a NaN NaN NaN NaN
b NaN NaN NaN NaN
c NaN NaN NaN NaN
В более поздних версиях панд мы можем достичь этого результата, используя iloc
и помощь другого метода:
>>> df.iloc[:df.index.get_loc('c') + 1, :4]
x y z 8
a NaN NaN NaN NaN
b NaN NaN NaN NaN
c NaN NaN NaN NaN
get_loc()
это индексный метод, означающий «получить позицию метки в этом индексе». Обратите внимание, что поскольку нарезка с iloc
не является конечной точкой, мы должны добавить 1 к этому значению, если хотим также строку 'c'.
В документации pandas есть дополнительные примеры .
iloc
работает на основе целочисленного позиционирования. Поэтому, независимо от того, какие метки ярлыков вы можете, например, получить первую строку, выполнив
df.iloc[0]
или последние пять строк, выполнив
df.iloc[-5:]
. Вы можете также используйте его на столбцах. Это извлекает третий столбец:
df.iloc[:, 2] # the : in the first position indicates all rows
Вы можете комбинировать их для получения пересечений строк и столбцов:
df.iloc[:3, :3] # The upper-left 3 X 3 entries (assuming df has 3+ rows and columns)
С другой стороны, .loc
используют именованные индексы. Давайте создадим кадр данных со строками в виде ярлыков строк и столбцов:
df = pd.DataFrame(index=['a', 'b', 'c'], columns=['time', 'date', 'name'])
Затем мы можем получить первую строку по
df.loc['a'] # equivalent to df.iloc[0]
, а вторую две строки в 'date'
столбца
df.loc['b':, 'date'] # equivalent to df.iloc[1:, 1]
и т. д. Теперь, вероятно, стоит отметить, что индексы строк и столбцов по умолчанию для DataFrame
являются целыми числами от 0, и в этом случае iloc
и loc
будут работать одинаково. Вот почему ваши три примера эквивалентны. Если у вас был нечисловой индекс, такой как строки или даты, df.loc[:5]
вызовет ошибку.
Кроме того, вы можете выполнить поиск столбцов только с помощью фрейма данных __getitem__
:
df['time'] # equivalent to df.loc[:, 'time']
Теперь предположим, что вы хотите смешать позицию и названную индексацию, то есть индексирование с использованием имена в строках и позициях в столбцах (чтобы уточнить, я имею в виду выбор из нашего фрейма данных, а не создание фрейма данных со строками в индексе строки и целых чисел в индексе столбца). Вот где .ix
приходит:
df.ix[:2, 'time'] # the first two rows of the 'time' column
EDIT: Я думаю, что также стоит упомянуть, что вы можете передавать логические векторы в метод loc
. Например:
b = [True, False, True]
df.loc[b]
Вернет 1-ю и 3-ю строки df
. Это эквивалентно df[b]
для выбора, но его также можно использовать для назначения через логические векторы:
df.loc[b, 'name'] = 'Mary', 'John'
df.loc[:, :]
. Его можно использовать для повторного назначения значений всего DataFrame
или создания его вида.
– JoeCondron
3 May 2017 в 20:45
loc
,iloc
иix
могут по-прежнему вызывать предупреждение, если они соединены вместе. Используя пример DataFrame в связанных документахdfmi.loc[:, 'one'].loc[:, 'second']
, запускается предупреждение так же, какdfmi['one']['second']
, потому что копия данных (а не представление) может быть возвращена первой операцией индексирования. – Alex Riley 23 July 2015 в 18:56df.ix[1:3, :'b']
оба этикета основаны на ярлыках. BTW, всегда приветствуем, чтобы улучшить документы, чтобы сделать вещи более ясными! – joris 24 July 2015 в 14:52