объяснение панд илок против IX и лок; насколько они разные?
Может кто-нибудь объяснить, как эти три метода нарезки различны?
Я видел документы,
и я видел эти ответы, но я все еще не могу объяснить, как эти три разные. Для меня они кажутся взаимозаменяемыми в значительной степени, потому что они находятся на более низких уровнях срезания.
Например, скажем, мы хотим получить первые пять строк DataFrame
. Как все это работает?
df.loc[:5]
df.ix[:5]
df.iloc[:5]
Может ли кто-нибудь представить три случая, когда различия в использовании понятнее?
Ответы
Ответ 1
Примечание: в версии pandas 0.20.0 и выше ix
устарела, и вместо этого рекомендуется использовать loc
и iloc
. Я оставил части этого ответа, которые описывают ix
intact как ссылку для пользователей более ранних версий панд. Примеры были добавлены ниже, показывая альтернативы ix
.
Во-первых, здесь приведено описание трех методов:
-
loc
получает строки (или столбцы) с определенными метками из индекса. -
iloc
получает строки (или столбцы) в определенных положениях индекса (так что он принимает только целые числа). -
ix
обычно пытается вести себя как loc
но возвращается к тому, чтобы вести себя как iloc
если метка отсутствует в индексе.
Это важно отметить некоторые тонкости, которые могут сделать ix
немного сложно использовать:
-
если индекс имеет целочисленный тип, 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
.
Если, однако, наш индекс был смешанного типа, то при 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
Как общий совет, если вы используете только индексирование с использованием меток или только индексирование с использованием целых позиций, придерживайтесь 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
В более ранних версиях pandas (до 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'.
Есть и другие примеры в документации панд здесь.
Ответ 2
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
Я думаю, что также стоит упомянуть, что вы также можете передавать логические векторы в метод loc
. Например:
b = [True, False, True]
df.loc[b]
Вернет 1-ю и 3-ю строки df
. Это эквивалентно df[b]
для выбора, но его также можно использовать для назначения через булевы векторы:
df.loc[b, 'name'] = 'Mary', 'John'
Ответ 3
На мой взгляд, принятый ответ сбивает с толку, поскольку он использует DataFrame только с пропущенными значениями. Мне также не нравится термин " основанный на положении" для .iloc
и вместо этого я предпочитаю целочисленное местоположение, так как он гораздо более описательный и именно то, что обозначает .iloc
. Ключевое слово - INTEGER - .iloc
нужны INTEGERS.
Смотрите мою чрезвычайно подробную серию блогов о выборе подмножеств
.ix устарела и неоднозначна и никогда не должна использоваться
Поскольку .ix
устарела, мы сосредоточимся только на различиях между .loc
и .iloc
.
Прежде чем говорить о различиях, важно понять, что в фреймах данных есть метки, которые помогают идентифицировать каждый столбец и каждый индекс. Давайте посмотрим на пример DataFrame:
df = pd.DataFrame({'age':[30, 2, 12, 4, 32, 33, 69],
'color':['blue', 'green', 'red', 'white', 'gray', 'black', 'red'],
'food':['Steak', 'Lamb', 'Mango', 'Apple', 'Cheese', 'Melon', 'Beans'],
'height':[165, 70, 120, 80, 180, 172, 150],
'score':[4.6, 8.3, 9.0, 3.3, 1.8, 9.5, 2.2],
'state':['NY', 'TX', 'FL', 'AL', 'AK', 'TX', 'TX']
},
index=['Jane', 'Nick', 'Aaron', 'Penelope', 'Dean', 'Christina', 'Cornelia'])
![enter image description here]()
Все слова, выделенные жирным шрифтом, являются метками. Метки, age
, color
, food
, height
, score
и state
используются для столбцов. Другие индексы, Jane
, Nick
, Aaron
, Penelope
, Dean
, Christina
, Cornelia
, используются для индекса.
Основными способами выбора отдельных строк в DataFrame являются индексаторы .loc
и .iloc
. Каждый из этих индексаторов также можно использовать для одновременного выбора столбцов, но сейчас проще просто сосредоточиться на строках. Кроме того, каждый из индексаторов использует набор скобок, которые сразу же следуют за их именем, чтобы сделать свой выбор.
.loc выбирает данные только по меткам
Сначала поговорим о индексаторе .loc
который выбирает данные только по меткам индекса или столбца. В нашем примере DataFrame мы предоставили значимые имена в качестве значений для индекса. Многие DataFrames не будут иметь каких-либо значимых имен и вместо этого по умолчанию будут просто целые числа от 0 до n-1, где n - длина DataFrame.
Для .loc
можно использовать три разных входа
- Строка
- Список строк
- Запись среза с использованием строк в качестве начального и конечного значений
Выбор одной строки с помощью .loc со строкой
Чтобы выбрать одну строку данных, поместите метку индекса внутри скобок после .loc
.
df.loc['Penelope']
Это возвращает строку данных в виде серии
age 4
color white
food Apple
height 80
score 3.3
state AL
Name: Penelope, dtype: object
Выбор нескольких строк с помощью .loc со списком строк
df.loc[['Cornelia', 'Jane', 'Dean']]
Это возвращает DataFrame со строками в порядке, указанном в списке:
![enter image description here]()
Выбор нескольких строк с помощью .loc с обозначением слайса
Обозначение среза определяется значениями start, stop и step. При разрезании по метке, pandas включает в себя значение остановки в возврате. Следующие кусочки от Аарона до Дина включительно. Размер шага явно не определен, но по умолчанию равен 1.
df.loc['Aaron':'Dean']
![enter image description here]()
Сложные фрагменты могут быть взяты так же, как списки Python.
.iloc выбирает данные только по целому расположению
Давай теперь обратимся к .iloc
. Каждая строка и столбец данных в DataFrame имеет целочисленное местоположение, которое определяет его. Это в дополнение к метке, которая визуально отображается в выходных данных. Целочисленное местоположение - это просто число строк/столбцов сверху/слева, начиная с 0.
Для .iloc
можно использовать три разных входа
- Целое число
- Список целых чисел
- Запись среза с использованием целых чисел в качестве начального и конечного значений
Выбор одной строки с .iloc с целым числом
df.iloc[4]
Это возвращает 5-ую строку (целочисленное местоположение 4) как серию
age 32
color gray
food Cheese
height 180
score 1.8
state AK
Name: Dean, dtype: object
Выбор нескольких строк с .iloc со списком целых чисел
df.iloc[[2, -2]]
Это возвращает DataFrame третьей и второй до последней строки:
![enter image description here]()
Выбор нескольких строк с .iloc с обозначением среза
df.iloc[:5:3]
![enter image description here]()
Одновременный выбор строк и столбцов с .loc и .iloc
Одной из отличных способностей обоих .loc/.iloc
является их способность выбирать строки и столбцы одновременно. В приведенных выше примерах все столбцы возвращались из каждого выбора. Мы можем выбрать столбцы с теми же типами входов, что и для строк. Нам просто нужно разделить выбор строки и столбца запятой.
Например, мы можем выбрать строки Джейн и Дина только с высотой, счетом и состоянием столбцов следующим образом:
df.loc[['Jane', 'Dean'], 'height':]
![enter image description here]()
При этом используется список меток для строк и нотации колонок для столбцов.
Естественно, мы можем делать аналогичные операции с .iloc
используя только целые числа.
df.iloc[[1,4], 2]
Nick Lamb
Dean Cheese
Name: food, dtype: object
Одновременный выбор с метками и целочисленным расположением
.ix
использовался, чтобы делать выборки одновременно с метками и целочисленным расположением, что было полезно, но .ix
с толку и неоднозначно, и, к счастью, это не рекомендуется. В случае, если вам нужно сделать выборку с сочетанием меток и целочисленных местоположений, вам нужно будет сделать метки выбора или целочисленные местоположения.
Например, если мы хотим выбрать строки Nick
и Cornelia
вместе со столбцами 2 и 4, мы могли бы использовать .loc
, преобразовав целые числа в метки со следующим:
col_names = df.columns[[2, 4]]
df.loc[['Nick', 'Cornelia'], col_names]
Или, в качестве альтернативы, преобразуйте метки индекса в целые числа с помощью get_loc
индекса get_loc
.
labels = ['Nick', 'Cornelia']
index_ints = [df.index.get_loc(label) for label in labels]
df.iloc[index_ints, [2, 4]]
Логическое выделение
Индексатор .loc также может выполнять логический выбор. Например, если мы заинтересованы в том, чтобы найти все строки, где возраст старше 30 лет, и вернуть только столбцы food
и score
мы можем сделать следующее:
df.loc[df['age'] > 30, ['food', 'score']]
Вы можете повторить это с помощью .iloc
но не можете передать его логическим сериям. Вы должны преобразовать логическую серию в массив numpy следующим образом:
df.iloc[(df['age'] > 30).values, [2, 4]]
Выбор всех строк
Можно использовать .loc/.iloc
только для выбора столбца. Вы можете выбрать все строки, используя двоеточие, как это:
df.loc[:, 'color':'score':2]
![enter image description here]()
Оператор индексирования []
может выбирать строки и столбцы, но не одновременно.
Большинству людей знакомо основное назначение оператора индексации DataFrame - выбор столбцов. Строка выбирает один столбец в качестве Серии, а список строк выбирает несколько столбцов в качестве DataFrame.
df['food']
Jane Steak
Nick Lamb
Aaron Mango
Penelope Apple
Dean Cheese
Christina Melon
Cornelia Beans
Name: food, dtype: object
Использование списка выбирает несколько столбцов
df[['food', 'score']]
![enter image description here]()
Люди менее знакомы с тем, что при использовании нотации среза выбор происходит по меткам строк или по целочисленному расположению. Это очень сбивает с толку и то, что я почти никогда не использую, но это работает.
df['Penelope':'Christina'] # slice rows by label
![enter image description here]()
df[2:6:2] # slice rows by integer location
![enter image description here]()
.loc/.iloc
для выбора строк очень предпочтительна. Один оператор индексирования не может одновременно выбирать строки и столбцы.
df[3:5, 'color']
TypeError: unhashable type: 'slice'
Ответ 4
Позвольте мне сказать вам, что ix был в предыдущих версиях pandas.and iloc, а loc включена в его последние версии.
- IX - это используется для анализа любых конкретных данных из фрейма данных с использованием либо метки, либо индекса строки и столбца за раз. Так что возникла небольшая проблема, как в некоторых случаях, когда индекс столбца и индекс строки оба были комбинацией числовых и строковых меток.
Пример: - df.ix[:2, 'time']
Теперь приходите в лока.
- Это анализирует данные, используя метки в качестве индекса, будь то столбец или строка.
Пример: - df.loc[:, 'color':'score':2]
Теперь для iloc.
- Что мы делаем, мы предоставляем столбец и строку в качестве индекса (обозначается номером)
Пример: - df.iloc[[1,4], 2]