Разница между скобками [] и двойной скобкой [[]] для доступа к элементам списка или кадра данных

r list dataframe extract r-faq

168261 просмотра

12 ответа

R предоставляет два разных метода для доступа к элементам списка или data.frame- []и [[]]операторам.

Какая разница между двумя? В каких ситуациях я должен использовать один над другим?

Автор: Sharpie Источник Размещён: 17.05.2019 03:53

Ответы (12)


271 плюса

Решение

Определение R-языка полезно для ответа на следующие типы вопросов:

R имеет три основных оператора индексирования: синтаксис, отображаемый в следующих примерах

    x[i]
    x[i, j]
    x[[i]]
    x[[i, j]]
    x$a
    x$"a"

Для векторов и матриц [[формы редко используются, хотя они имеют некоторые незначительные смысловые отличия от [формы (например, он отбрасывает любые имена или атрибуты dimnames, а частичное совпадение используется для символьных индексов). При индексировании многомерных структур с одним индексом x[[i]]или x[i]возвращении iпоследовательного элемента x.

Для списков обычно используется [[для выбора любого отдельного элемента, тогда как [возвращает список выбранных элементов.

[[Форма позволяет только один элемент , который будет выбран с помощью целочисленных или символьных индексов, в то время как [позволяет индексировать векторами. Обратите внимание, что для списка индекс может быть вектором, и каждый элемент вектора применяется в свою очередь к списку, выбранному компоненту, выбранному компоненту этого компонента и т. Д. В результате все еще остается один элемент.

Автор: ars Размещён: 23.07.2009 03:46

148 плюса

Существенными различиями между этими двумя методами являются класс возвращаемых объектов при использовании для извлечения и могут ли они принимать диапазон значений или просто одно значение при назначении.

Рассмотрим случай извлечения данных в следующем списке:

foo <- list( str='R', vec=c(1,2,3), bool=TRUE )

Скажем, мы хотели бы извлечь значение, сохраненное bool из foo, и использовать его внутри if()оператора. Это иллюстрирует различия между значениями возврата []и [[]]их использованием для извлечения данных. []Метод возвращает список объектов класса (или data.frame , если Foo был data.frame) в то время как [[]]метод возвращает объекты, класс определяется типом их значения.

Таким образом, использование []метода приводит к следующему:

if( foo[ 'bool' ] ){ print("Hi!") }
Error in if (foo["bool"]) { : argument is not interpretable as logical

class( foo[ 'bool' ] )
[1] "list"

Это связано с тем, что []метод возвратил список, а список недействителен для передачи непосредственно в if()оператор. В этом случае нам нужно использовать, [[]]потому что он вернет «голый» объект, хранящийся в «bool», который будет иметь соответствующий класс:

if( foo[[ 'bool' ]] ){ print("Hi!") }
[1] "Hi!"

class( foo[[ 'bool' ]] )
[1] "logical"

Второе отличие состоит в том, что []оператор может использоваться для доступа к диапазону слотов в списке или столбцах в кадре данных, в то время как [[]]оператор ограничен доступом к одному слоту или столбцу. Рассмотрим случай присвоения значений, используя второй список bar():

bar <- list( mat=matrix(0,nrow=2,ncol=2), rand=rnorm(1) )

Скажем, мы хотим перезаписать последние два слота foo данными, содержащимися в баре. Если мы попытаемся использовать [[]]оператор, это произойдет:

foo[[ 2:3 ]] <- bar
Error in foo[[2:3]] <- bar : 
more elements supplied than there are to replace

Это связано с [[]]ограничением доступа к одному элементу. Нам нужно использовать []:

foo[ 2:3 ] <- bar
print( foo )

$str
[1] "R"

$vec
     [,1] [,2]
[1,]    0    0
[2,]    0    0

$bool
[1] -0.6291121

Обратите внимание, что, хотя назначение было успешным, слоты в foo сохранили свои исходные имена.

Автор: Sharpie Размещён: 23.07.2009 03:57

91 плюса

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

lst <- list('one','two','three')

a <- lst[1]
class(a)
## returns "list"

a <- lst[[1]]
class(a)
## returns "character"
Автор: medriscoll Размещён: 23.07.2009 03:48

39 плюса

[]извлекает список, [[]]извлекает элементы из списка

alist <- list(c("a", "b", "c"), c(1,2,3,4), c(8e6, 5.2e9, -9.3e7))

str(alist[[1]])
 chr [1:3] "a" "b" "c"

str(alist[1])
List of 1
 $ : chr [1:3] "a" "b" "c"

str(alist[[1]][1])
 chr "a"
Автор: user143339 Размещён: 23.07.2009 03:50

20 плюса

От Хэдли Уикхема:

От Хэдли Уикхема

Моя (дерьмовая) модификация, показывающая использование tidyverse / purrr:

введите описание изображения здесь

Автор: jzadra Размещён: 06.04.2018 07:38

16 плюса

Просто добавление здесь, которое [[также оснащено для рекурсивного индексирования .

Это было намечено в ответе @JijoMatthew, но не исследовано.

Как отмечено в ?"[[", синтаксис вроде x[[y]], где length(y) > 1, интерпретируется как:

x[[ y[1] ]][[ y[2] ]][[ y[3] ]] ... [[ y[length(y)] ]]

Обратите внимание, что это не изменяет того, что должно быть вашим основным выводом на разницу между [и [[- а именно, что первый используется для подмножества , а последний используется для извлечения отдельных элементов списка.

Например,

x <- list(list(list(1), 2), list(list(list(3), 4), 5), 6)
x
# [[1]]
# [[1]][[1]]
# [[1]][[1]][[1]]
# [1] 1
#
# [[1]][[2]]
# [1] 2
#
# [[2]]
# [[2]][[1]]
# [[2]][[1]][[1]]
# [[2]][[1]][[1]][[1]]
# [1] 3
#
# [[2]][[1]][[2]]
# [1] 4
#
# [[2]][[2]]
# [1] 5
#
# [[3]]
# [1] 6

Чтобы получить значение 3, мы можем сделать:

x[[c(2, 1, 1, 1)]]
# [1] 3

Возвращаясь к ответу @ JijoMatthew выше, напомните r:

r <- list(1:10, foo=1, far=2)

В частности, это объясняет ошибки, которые мы склонны получать при неправильном использовании [[, а именно:

r[[1:3]]

Ошибка r[[1:3]]: рекурсивная индексация не удалась на уровне 2

Так как этот код на самом деле пытался оценить r[[1]][[2]][[3]], а вложенность rостановок на первом уровне, попытка извлечь из рекурсивного индексации не удалась [[2]], т. Е. На уровне 2.

Ошибка в r[[c("foo", "far")]]: индексе вне пределов

Здесь R искал r[["foo"]][["far"]], чего не существует, поэтому мы получаем ошибку индекса.

Вероятно, это было бы немного более полезно / непротиворечиво, если бы обе эти ошибки дали одно и то же сообщение.

Автор: MichaelChirico Размещён: 30.04.2016 08:29

14 плюса

Оба они - способы подмножества. Единая скобка вернет подмножество списка, которое само по себе будет списком. т.е.: оно может содержать или не содержать более одного элемента. С другой стороны, двойная скобка возвращает только один элемент из списка.

-Согласная скобка предоставит нам список. Мы также можем использовать одиночную скобку, если хотим вернуть несколько элементов из списка. рассмотрите следующий список: -

>r<-list(c(1:10),foo=1,far=2);

Теперь обратите внимание, как возвращается список, когда я пытаюсь его отобразить. Я набираю r и нажимаю enter

>r

#the result is:-

[[1]]

 [1]  1  2  3  4  5  6  7  8  9 10

$foo

[1] 1

$far

[1] 2

Теперь мы увидим магию одной скобки: -

>r[c(1,2,3)]

#the above command will return a list with all three elements of the actual list r as below

[[1]]

 [1]  1  2  3  4  5  6  7  8  9 10

$foo

[1] 1


$far

[1] 2

что точно так же, как когда мы пытались отобразить значение r на экране, что означает, что использование одной скобки вернуло список, где в индексе 1 у нас есть вектор из 10 элементов, то у нас есть еще два элемента с именами foo и далеко. Мы также можем указать один индекс или имя элемента в качестве входных данных для одной скобки. например:

> r[1]

[[1]]

 [1]  1  2  3  4  5  6  7  8  9 10

В этом примере мы дали один индекс «1» и в ответ получили список с одним элементом (который представляет собой массив из 10 чисел)

> r[2]

$foo

[1] 1

В приведенном выше примере мы дали один индекс «2» и взамен получили список с одним элементом

> r["foo"];

$foo

[1] 1

В этом примере мы передали имя одного элемента, и в результате список был возвращен одним элементом.

Вы также можете передать вектор имен элементов, таких как: -

> x<-c("foo","far")

> r[x];

$foo

[1] 1

$far
[1] 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.

Я приведу несколько примеров. Пожалуйста, обратите внимание на слова, выделенные жирным шрифтом, и вернитесь к нему после того, как вы закончите с приведенными ниже примерами:

Двойная скобка вернет вам фактическое значение в индексе (он НЕ вернет список)

  > r[[1]]

     [1]  1  2  3  4  5  6  7  8  9 10


  >r[["foo"]]

    [1] 1

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

Рассмотрим следующее

> r[[c(1:3)]]
Error in r[[c(1:3)]] : recursive indexing failed at level 2
> r[[c(1,2,3)]]
Error in r[[c(1, 2, 3)]] : recursive indexing failed at level 2
> r[[c("foo","far")]]
Error in r[[c("foo", "far")]] : subscript out of bounds
Автор: Jijo Mathew Размещён: 30.08.2014 01:48

12 плюса

Чтобы помочь новичкам перемещаться по ручному туману, было бы полезно увидеть [[ ... ]]обозначение как функцию свертывания - другими словами, именно тогда, когда вы просто хотите «получить данные» из именованного вектора, списка или фрейма данных. Это полезно сделать, если вы хотите использовать данные из этих объектов для расчетов. Эти простые примеры иллюстрируют.

(x <- c(x=1, y=2)); x[1]; x[[1]]
(x <- list(x=1, y=2, z=3)); x[1]; x[[1]]
(x <- data.frame(x=1, y=2, z=3)); x[1]; x[[1]]

Итак, из третьего примера:

> 2 * x[1]
  x
1 2
> 2 * x[[1]]
[1] 2
Автор: Redfoot Размещён: 24.01.2013 10:08

7 плюса

Для еще одного конкретного варианта использования используйте двойные скобки, когда вы хотите выбрать кадр данных, созданный split()функцией. Если вы не знаете, split()группирует кадр списка / данных в подмножества на основе ключевого поля. Это полезно, если вы хотите работать с несколькими группами, строить их и т. Д.

> class(data)
[1] "data.frame"

> dsplit<-split(data, data$id)
> class(dsplit)
[1] "list"

> class(dsplit['ID-1'])
[1] "list"

> class(dsplit[['ID-1']])
[1] "data.frame"
Автор: Peter Размещён: 04.05.2012 09:07

6 плюса

Будучи терминологическим, [[оператор извлекает элемент из списка, тогда как [оператор принимает подмножество списка.

Автор: submartingale Размещён: 06.08.2017 09:54

0 плюса

К тому же:

После LINK в ОТВЕТА здесь.

Вот небольшой пример, касающийся следующего пункта:

x[i, j] vs x[[i, j]]

df1   <- data.frame(a = 1:3)
df1$b <- list(4:5, 6:7, 8:9)

df1[[1,2]]
df1[1,2]

str(df1[[1,2]])
str(df1[1,2])
Автор: Andre Elrico Размещён: 06.11.2018 02:36

-1 плюса

Пожалуйста, обратитесь к ниже подробному объяснению.

Я использовал встроенный фрейм данных в R, называемый mtcars.

> mtcars 
               mpg cyl disp  hp drat   wt ... 
Mazda RX4     21.0   6  160 110 3.90 2.62 ... 
Mazda RX4 Wag 21.0   6  160 110 3.90 2.88 ... 
Datsun 710    22.8   4  108  93 3.85 2.32 ... 
           ............

Верхняя строка таблицы называется заголовком, который содержит имена столбцов. Каждая горизонтальная линия впоследствии обозначает строку данных, которая начинается с имени строки, а затем за ней следуют фактические данные. Каждый элемент данных строки называется ячейкой.

одиночная квадратная скобка "[]"

Для извлечения данных в ячейке мы вводим его координаты строк и столбцов в одиночном квадратном скобке «[]». Две координаты разделены запятой. Другими словами, координаты начинаются с позиции строки, затем за запятой и заканчиваются позицией столбца. Порядок важен.

Например, 1: - Здесь значение ячейки из первой строки, второй столбец mtcars.

> mtcars[1, 2] 
[1] 6

Например, 2: - Кроме того, мы можем использовать имена строк и столбцов вместо числовых координат.

> mtcars["Mazda RX4", "cyl"] 
[1] 6 

Двойная квадратная скобка "[[]]" оператор

Мы ссылаемся на столбец фреймов данных с помощью оператора двойной квадратной скобки [[]].

Например, 1: - Чтобы получить девятый вектор столбца встроенного набора данных mtcars, мы пишем mtcars [[9]].

mtcars [[9]] [1] 1 1 1 0 0 0 0 0 0 0 0 ...

Например, 2: - Мы можем получить один и тот же вектор столбца по его названию.

mtcars [["am"]] [1] 1 1 1 0 0 0 0 0 0 0 0 ...

Автор: Prasan Karunarathne Размещён: 05.09.2018 10:27
Вопросы из категории :
32x32