Каковы различия между операторами присваивания
=
и<-
в R?Как показывает ваш пример,
=
и<-
имеют несколько иные приоритет оператора (который определяет порядок оценки, когда они смешиваются в одном выражении). Фактически,?Syntax
в R дает следующую таблицу приоритета оператора: от наивысшего до самого низкого:… ‘-> ->>’ rightwards assignment ‘<- <<-’ assignment (right to left) ‘=’ assignment (right to left) …
Но это единственная разница ?
Поскольку вы спрашивали о операторах присваивания : да, это единственная разница. Однако вам будет отказано в вере. Даже документация R в
?assignOps
утверждает, что существует больше различий:Оператор
<-
можно использовать в любом месте, тогда как оператор=
разрешено на верхнем уровне (например, в полном выражении, введенном в командной строке) или в качестве одного из подвыражений в скобках списка выражений.Давайте не будем слишком тонко очертить это: R-документация (тонко) неверна [ 1 ]. Это легко показать: нам просто нужно найти встречный пример оператора
=
, который не является (a) на верхнем уровне, и (b) подвыражение в скобках списка выражений (т.е.{…; …}
). - Без дальнейших церемоний:x # Error: object 'x' not found sum((x = 1), 2) # [1] 3 x # [1] 1
Очевидно, что мы выполнили назначение, используя
=
, вне контекстов (a) и (b). Итак, почему документация о ключевой языковой функции R была неправильной на протяжении десятилетий?Это связано с тем, что в синтаксисе R символ
=
имеет два разных значения, которые обычно объединяются:
- Первое значение является оператором присваивания . Это все, о чем мы говорили до сих пор.
- Второе значение - это не оператор, а токен синтаксиса , который сигнализирует с именем аргумент, передающий в вызове функции. В отличие от оператора
=
он не выполняет никаких действий во время выполнения, он просто меняет способ анализа выражения.Давайте посмотрим.
В любом фрагменте кода общая форма ...
‹function_name›(‹argname› = ‹value›, …) ‹function_name›(‹args›, ‹argname› = ‹value›, …)
...
=
- это токен, который определяет передачу именованных аргументов: это not оператор присваивания. Кроме того,=
полностью запрещен в некоторых синтаксических контекстах:if (‹var› = ‹value›) … while (‹var› = ‹value›) … for (‹var› = ‹value› in ‹value2›) … for (‹var1› in ‹var2› = ‹value›) …
Любой из них вызовет ошибку «неожиданный» = «в
».
В любом другом контексте
=
ссылается на вызов оператора присваивания. В частности, просто размещение круглых скобок вокруг подвыражения делает любой из вышеперечисленных (a) действительными и (b) присвоением . Например, следующее выполняет назначение:median((x = 1 : 10))
Но также:
if (! (nf = length(from))) return()
Теперь вы можете возразить, что такой код является жестоким (и вы можете быть правы). Но я взял этот код из функции
base::file.copy
(заменив<-
на=
) - это распространенный шаблон в большей части основной базы кода R.Исходное объяснение от John Chambers , на котором, вероятно, основана документация R, на самом деле объясняет это правильно:
[
=
присваивание] разрешено только в двух местах в грамматике: на верхнем уровне (как полная программа или пользовательское выражение); и когда они изолированы от окружающей логической структуры, скобками или дополнительной парой круглых скобок.Исповедь: я солгал раньше. Там есть еще одно различие между операторами
=
и<-
: они вызывают различные функции. По умолчанию эти функции выполняют одно и то же, но вы можете переопределить любой из них отдельно, чтобы изменить поведение. Напротив,<-
и->
(назначение слева направо), хотя и синтаксически различны, всегда вызывают функцию же . Переопределение одного также переопределяет другое. Знание этого редко бывает практичным , но оно может быть использовано для некоторых забавных махинаций .
Это называется сводной таблицей. Нехорошо производить:
SELECT ID,
MAX(CASE Type WHEN 202 THEN Degignation END) AS `202`
MAX(CASE Type WHEN 234 THEN Degignation END) AS `234`
MAX(CASE Type WHEN 239 THEN Degignation END) AS `239`
Email
FROM mytable
GROUP BY ID, Email
Обратите внимание, что перед записью запроса вы должны знать все разные значения Type
. SQL не позволяет набору результатов динамически добавлять больше столбцов, поскольку он обнаруживает значения данных в таблице. Столбцы должны быть зафиксированы на этапе подготовки запроса.
Хотя ответ Билла Карвина - правильный запрос, должен знать определенный набор столбцов, но для динамического сводного запроса существует способ взлома с помощью group_concat
SET @sql = NULL;
SELECT GROUP_CONCAT(DISTINCT
CONCAT('MAX(CASE WHEN `Type` = ''',
`Type`,
''' THEN Degignation END) `Type_',
`Type`,
'`'
)
)
INTO @sql
FROM t;
SET @sql = CONCAT('SELECT ID, ', @sql, ', Email
FROM t
GROUP BY ID,Email');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Однако, используя
blockquote>group_concat
, она имеет ограничение по умолчанию 1024 символа для конкатенации, а оставшийся результат будет усекается, поэтому, если у вас есть много разных типов, это будет сложно. Хотя вы можете увеличить предел для ограничения длиныgroup_concat
, как указано в руководстве, но также имеет зависимость отmax_allowed_packet