В чем разница между с и внутри в R?

Я всегда использую with вместо внутри в контексте моего исследования, но изначально я думал, что это одно и то же. Только что я опечатался с for внутри, и возвращаемые результаты совсем другие. Мне интересно, почему?

Я использую бейсбольные данные в пакете plyr, поэтому сначала загружаю библиотеку

 require(plyr)

Затем я хочу выбрать все строки с идентификатором ansonca01. Сначала, как я уже сказал, я использовал within и запускал функцию следующим образом:

within(baseball, baseball[id=="ansonca01", ])

Я получил очень странные результаты, которые в основном включают в себя все:

       id year stint team lg   g  ab   r   h X2b X3b hr rbi  sb cs  bb  so ibb hbp sh sf gidp
4     ansonca01 1871     1  RC1     25 120  29  39  11   3  0  16   6  2   2   1  NA  NA NA NA   NA
44    forceda01 1871     1  WS3     32 162  45  45   9   4  0  29   8  0   4   0  NA  NA NA NA   NA
68    mathebo01 1871     1  FW1     19  89  15  24   3   1  0  10   2  1   2   0  NA  NA NA NA   NA
99    startjo01 1871     1  NY2     33 161  35  58   5   1  1  34   4  2   3   0  NA  NA NA NA   NA
102   suttoez01 1871     1  CL1     29 128  35  45   3   7  3  23   3  1   1   0  NA  NA NA NA   NA
106   whitede01 1871     1  CL1     29 146  40  47   6   5  1  21   2  2   4   1  NA  NA NA NA   NA
113    yorkto01 1871     1  TRO     29 145  36  37   5   7  2  23   2  2   9   1  NA  NA NA NA   NA
.........

Затем я использую с вместо внутри,

 with(baseball, baseball[id=="ansonca01",])

и получил результаты, которые я ожидал

      id year stint team lg   g  ab   r   h X2b X3b hr rbi sb cs  bb so ibb hbp sh sf gidp
4    ansonca01 1871     1  RC1     25 120  29  39  11   3  0  16  6  2   2  1  NA  NA NA NA   NA
121  ansonca01 1872     1  PH1     46 217  60  90  10   7  0  50  6  6  16  3  NA  NA NA NA   NA
276  ansonca01 1873     1  PH1     52 254  53 101   9   2  0  36  0  2   5  1  NA  NA NA NA   NA
398  ansonca01 1874     1  PH1     55 259  51  87   8   3  0  37  6  0   4  1  NA  NA NA NA   NA
525  ansonca01 1875     1  PH1     69 326  84 106  15   3  0  58 11  6   4  2  NA  NA NA NA   NA

Я проверил документацию с и внутри, набрав help(with) в среде R, и получил следующее:

with — это универсальная функция, которая вычисляет expr в локальной среде, построенной на основе данных. Среда имеет среду вызывающего объекта в качестве родителя. Это полезно для упрощения вызовов функций моделирования. (Примечание: если данные уже являются средой, то она используется со своим существующим родителем.)

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

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

Из этого объяснения различий я не понимаю, почему я получил разные результаты с такой простой операцией. У кого-нибудь есть идеи?


person nan    schedule 17.02.2014    source источник
comment
Почему вы вообще используете with в утверждении вроде: with(baseball,baseball[id=="ansonca01",])? Вам просто нужно baseball[baseball$id=="ansonca01",].   -  person Thomas    schedule 17.02.2014
comment
within возвращает полный кадр данных. Выполнение извлечения внутри within на самом деле не имеет никакого смысла. Попробуйте создать новую переменную внутри with и внутри within, и вы увидите разницу более четко.   -  person Thomas    schedule 17.02.2014
comment
@Thomas Привет, конечно, я знаю, что могу сделать подмножество с бейсболом[baseball$id==ansonca01,], и на самом деле я всегда делал это таким образом. Сегодня я просто хотел попробовать что-то другое, и я обнаружил, что с и внутри возвращаются разные результаты для такой простой операции. Я хочу понять почему!!! Я узнал, что внутри для создания новых переменных, но это не отвечает на мой вопрос, размещенный здесь, почему эти две функции приводят к разным результатам в случае подмножества?   -  person nan    schedule 17.02.2014
comment
@Thomas Дело в том, что в этом примере я указал только одно условие для подмножества, а именно [id==ansonca01]. Если я хочу указать больше условий для разных столбцов, мне нужно много раз набирать baseball$somevariable или выполнять присоединение/отсоединение, with/inin, возможно, это хорошо для экономии усилий.   -  person nan    schedule 17.02.2014
comment
так как вы загружаете plyr, вы также можете попробовать summarise и mutate.   -  person baptiste    schedule 17.02.2014
comment
... и еще лучше, их dplyr двоюродных братьев.   -  person baptiste    schedule 17.02.2014
comment
на самом деле, первая часть вопроса, я хочу выбрать все строки... требует subset(baseball, id=="ansonca01")   -  person baptiste    schedule 17.02.2014


Ответы (3)


В документации довольно ясно говорится о семантика и возвращаемые значения (и хорошо соответствует повседневным значениям слов «с» и «внутри»):

Стоимость:

Для «with» значение оцененного «expr». Для «within» измененный объект.

Поскольку ваш код ничего не изменяет внутри baseball, возвращается немодифицированный baseball. with, с другой стороны, не возвращает объект, он возвращает expr.

Вот пример, где expression изменяет объект:

> head(within(cars, speed[dist < 20] <- 1))
  speed dist
1     1    2
2     1   10
3     1    4
4     7   22
5     1   16
6     1   10
person Konrad Rudolph    schedule 17.02.2014
comment
Думаю, это ответ на мой вопрос. На самом деле я прочитал содержимое, которое вы цитировали из документации, но я не полностью понял это предложение (для «с» значение оцениваемого «выражения». Для «внутри» - измененный объект), когда я его читал. Ваше объяснение помогает мне переосмыслить это, и оно имеет смысл. Теперь я понимаю, что with возвращает результат выражения. Внутри, если вы ничего не изменяете, возвращается исходный объект. Спасибо! - person nan; 17.02.2014
comment
можете ли вы сказать, как r проверяет, изменен ли объект в случае within, проверяя наличие <-? - person SIslam; 23.03.2017
comment
@SIslam Это не проверить. Он просто оценивает выражение, которое вы передаете через within, и выполняет оценку внутри фрейма данных. - person Konrad Rudolph; 23.03.2017

Я считаю, что простые примеры часто помогают подчеркнуть разницу. Что-то типа:

df <- data.frame(a=1:5,b=2:6)
df
  a b
1 1 2
2 2 3
3 3 4
4 4 5
5 5 6

with(df, {c <- a + b; df;} )
  a b
1 1 2
2 2 3
3 3 4
4 4 5
5 5 6

within(df, {c <- a + b; df;} )
# equivalent to: within(df, c <- a + b)
# i've just made the return of df explicit 
# for comparison's sake
  a b  c
1 1 2  3
2 2 3  5
3 3 4  7
4 4 5  9
5 5 6 11
person thelatemail    schedule 17.02.2014

Как и выше, with возвращает значение последнего вычисленного выражения. Это удобно для однострочников, таких как:

with(cars, summary(lm (speed ~ dist)))

но не подходит для отправки нескольких выражений.

Я часто нахожу within полезным для манипулирования data.frame или list (или data.table), так как синтаксис легко читается.

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

df1 <- data.frame(a=1:3,
              b=4:6,
              c=letters[1:3])
## library("data.table")  
## df1 <- as.data.table(df1)
df1 <- within(df1, {
    a <- 10:12
    b[1:2] <- letters[25:26]
    c <- a
})
df1

давать

    a b  c
1: 10 y 10
2: 11 z 11
3: 12 6 12

а также

df1 <- as.list(df1)
df1 <- within(df1, {
    a <- 20:23
    b[1:2] <- letters[25:26]
    c <- paste0(a, b)
})
df1

давать

$a
[1] 20 21 22 23

$b
[1] "y" "z" "6"

$c
[1] "20y" "21z" "226" "23y"

Также обратите внимание, что methods("within") дает только эти типы объектов, а именно:

  • within.data.frame
  • within.list
  • within.data.table, если пакет загружен).

Другие пакеты могут определять дополнительные методы.

Возможно, неожиданно для некоторых, with и within обычно не подходят для манипулирования переменными в определенных средах...

Чтобы адресовать комментарий - нет within.environment метода. Использование with требует, чтобы функция, которую вы вызываете, была внутри среды, что несколько противоречит цели для меня, например.

df1 <- as.environment(df1)
## with(df1, ls()) ## Error
assign("ls", ls, envir=df1)
with(df1, ls())
person dardisco    schedule 16.09.2018
comment
не могли бы вы пояснить свое последнее предложение немного подробнее? - person Ben Bolker; 16.09.2018