R предоставляет два разных метода для доступа к элементам списка или data.frame: []
и [[]]
.
В чем разница между этими двумя, в каких ситуациях я должен использовать один над другим?
Определение языка R удобно для ответа на следующие вопросы:
R имеет три основных оператора индексации, синтаксис которых показан в следующих примерах
x[i] x[i, j] x[[i]] x[[i, j]] x$a x$"a"
Для векторов и матриц
[[
формы используются редко, хотя они имеют некоторые небольшие семантические отличия от[
формы (например, он отбрасывает любые атрибуты names или dimnames, и это частичное соответствие используется для индексов символов). При индексации многомерных структур с одним индексомx[[i]]
илиx[i]
будет возвращатьсяi
последовательный элементx
.Для списков обычно используется
[[
для выбора любого отдельного элемента, тогда как[
возвращает список выбранных элементов.
[[
Форма позволяет только один элемент , который будет выбран с помощью целочисленных или символьных индексов, в то время как[
позволяет индексировать векторами. Обратите внимание, что для списка индекс может быть вектором, и каждый элемент вектора применяется по очереди к списку, выбранному компоненту, выбранному компоненту этого компонента и так далее. Результат по-прежнему один элемент.
[
всегда возвращаемого списка означает, что вы получаете один и тот же класс выводаx[v]
независимо от длиныv
. Например, один может понадобитьсяlapply
более чем подмножество списка:lapply(x[v], fun)
. Если[
бы исключить список для векторов длины один, это вернуло бы ошибку всякий раз, когдаv
имеет длину один.Существенными различиями между этими двумя методами являются класс объектов, которые они возвращают при использовании для извлечения, и могут ли они принимать диапазон значений или только одно значение во время присваивания.
Рассмотрим случай извлечения данных в следующем списке:
Скажем, мы хотели бы извлечь значение, сохраненное в bool, из foo и использовать его внутри
if()
оператора. Это проиллюстрирует различия между возвращаемыми значениями[]
и[[]]
когда они используются для извлечения данных. В[]
метод возвращает список объектов класса (или data.frame , если Foo был data.frame) в то время как[[]]
метод возвращает объекты , чей класс определяется типом их значений.Итак, использование
[]
метода приводит к следующему:Это связано с тем, что
[]
метод возвратил список, а список не является допустимым объектом для передачи непосредственно вif()
оператор. В этом случае нам нужно использовать,[[]]
потому что он вернет «голый» объект, хранящийся в «bool», который будет иметь соответствующий класс:Второе отличие состоит в том, что
[]
оператор может использоваться для доступа к диапазону интервалов в списке или столбцах в кадре данных, в то время как[[]]
оператор ограничен доступом к одному интервалу или столбцу. Рассмотрим случай присвоения значения с использованием второго спискаbar()
:Скажем, мы хотим перезаписать последние два слота foo данными, содержащимися в строке. Если мы попытаемся использовать
[[]]
оператор, вот что происходит:Это потому, что
[[]]
ограничен доступ к одному элементу. Нам нужно использовать[]
:Обратите внимание, что пока назначение было успешным, слоты в foo сохранили свои первоначальные имена.
источник
Двойные скобки обращаются к элементу списка , в то время как одна скобка возвращает вам список с одним элементом.
источник
От Хэдли Уикхем:
Моя (на вид дрянная) модификация для отображения с использованием tidyverse / purrr:
источник
[]
извлекает список,[[]]
извлекает элементы из спискаисточник
Просто добавив сюда, что
[[
также оборудовано для рекурсивной индексации .На это намекнул @JijoMatthew, но не исследовал.
Как отмечено в
?"[["
, синтаксис, подобныйx[[y]]
, гдеlength(y) > 1
, интерпретируется как:Обратите внимание, что это не меняет того, что должно быть вашим основным понятием разницы между
[
и[[
- а именно, что первое используется для поднабора , а второе используется для извлечения отдельных элементов списка.Например,
Чтобы получить значение 3, мы можем сделать:
Возвращаясь к ответу @ JijoMatthew выше, вспомните
r
:В частности, это объясняет ошибки, которые мы склонны получать при неправильном использовании
[[
, а именно:Поскольку этот код фактически пытался оценить
r[[1]][[2]][[3]]
, а вложенностьr
останавливается на первом уровне, попытка извлечь с помощью рекурсивной индексации не удалась на уровне[[2]]
, то есть на уровне 2.Здесь R искал
r[["foo"]][["far"]]
, чего не существует, поэтому мы получаем ошибку индекса за пределами границ.Вероятно, было бы немного более полезным / последовательным, если бы обе эти ошибки дали одно и то же сообщение.
источник
Оба они являются способами поднабора. Одиночная скобка вернет подмножество списка, которое само по себе будет списком. То есть: может содержать или не содержать более одного элемента. С другой стороны, двойная скобка вернет только один элемент из списка.
Одиночная скобка даст нам список. Мы также можем использовать одну скобку, если мы хотим вернуть несколько элементов из списка. рассмотрим следующий список:
Теперь обратите внимание, как возвращается список, когда я пытаюсь его отобразить. Я набираю r и нажимаю ввод
Теперь мы увидим магию одиночной скобки: -
что точно так же, как когда мы пытались отобразить значение r на экране, что означает, что использование одиночной скобки вернул список, где по индексу 1 у нас есть вектор из 10 элементов, тогда у нас есть еще два элемента с именами foo и далеко. Мы также можем выбрать один индекс или имя элемента в качестве ввода для одной скобки. например:
В этом примере мы дали один индекс «1» и взамен получили список с одним элементом (который представляет собой массив из 10 чисел)
В приведенном выше примере мы дали один индекс «2» и взамен получили список с одним элементом
В этом примере мы передали имя одного элемента, а взамен был возвращен список с одним элементом.
Вы также можете передать вектор имен элементов, таких как: -
В этом примере мы передали вектор с двумя именами элементов "foo" и "far"
Взамен мы получили список с двумя элементами.
Короче говоря, одна скобка всегда вернет вам другой список с количеством элементов, равным количеству элементов или количеству индексов, которые вы передаете в одну скобку.
Напротив, двойная скобка всегда будет возвращать только один элемент. Прежде чем переходить на двойные скобки, следует помнить.
NOTE:THE MAJOR DIFFERENCE BETWEEN THE TWO IS THAT SINGLE BRACKET RETURNS YOU A LIST WITH AS MANY ELEMENTS AS YOU WISH WHILE A DOUBLE BRACKET WILL NEVER RETURN A LIST. RATHER A DOUBLE BRACKET WILL RETURN ONLY A SINGLE ELEMENT FROM THE LIST.
Я приведу несколько примеров. Пожалуйста, запишите слова жирным шрифтом и вернитесь к ним после того, как закончите с примерами ниже:
Двойная скобка вернет вам фактическое значение по индексу. ( НЕ вернет список)
для двойных скобок, если мы попытаемся просмотреть более одного элемента, передав вектор, это приведет к ошибке только потому, что она создана не для удовлетворения этой потребности, а просто для возврата одного элемента.
Рассмотрим следующее
источник
[]
класс списка возвращается, даже если он представляет собой одну цифру, очень не интуитивно понятен. Им следовало создать другой синтаксис, подобный([])
списку, и[[]]
для доступа к фактическому элементу все в порядке. Я предпочитаю воспринимать[[]]
как необработанную ценность, как и в других языках.Чтобы помочь новичкам перемещаться по ручному туману, было бы полезно рассматривать
[[ ... ]]
нотацию как сворачивающуюся функцию - другими словами, это когда вы просто хотите «получить данные» из именованного вектора, списка или фрейма данных. Это хорошо сделать, если вы хотите использовать данные этих объектов для расчетов. Эти простые примеры проиллюстрируют.Итак, из третьего примера:
источник
iris[[1]]
возвращает вектор, тогда какiris[1]
возвращает data.frameБудучи терминологическим,
[[
оператор извлекает элемент из списка, тогда как[
оператор берет подмножество списка.источник
Для еще одного конкретного случая использования используйте двойные скобки, когда вы хотите выбрать фрейм данных, созданный
split()
функцией. Если вы не знаете,split()
группируйте список / фрейм данных в подмножества на основе ключевого поля. Это полезно, если вы хотите работать с несколькими группами, строить их и т. Д.источник
Пожалуйста, обратитесь к подробному объяснению ниже.
Я использовал встроенный фрейм данных в R, называемый mtcars.
Верхняя строка таблицы называется заголовком, который содержит имена столбцов. Каждая горизонтальная линия после этого обозначает строку данных, которая начинается с имени строки, а затем сопровождается фактическими данными. Каждый элемент данных строки называется ячейкой.
оператор с квадратной скобкой "[]"
Чтобы получить данные в ячейке, мы должны ввести ее координаты строки и столбца в одной квадратной скобке оператора «[]». Две координаты разделены запятой. Другими словами, координаты начинаются с позиции строки, затем следуют запятая и заканчиваются позицией столбца. Порядок важен.
Например: 1 - это значение ячейки из первого ряда, второго столбца mtcars.
Например, 2: - Кроме того, мы можем использовать имена строк и столбцов вместо числовых координат.
Оператор двойной квадратной скобки "[[]]"
Мы ссылаемся на столбец фрейма данных оператором [[]] двойной квадратной скобки.
Например, 1: - Чтобы получить вектор девятого столбца встроенного набора данных mtcars, мы пишем mtcars [[9]].
Например, 2: - Мы можем получить тот же вектор столбца по его имени.
источник
К тому же:
После LINK в ОТВЕТА здесь.
Вот небольшой пример, посвященный следующему пункту:
x[i, j] vs x[[i, j]]
источник