Spec-Zone.ru › Julia 0.7

Пропущенные значения

Julia предоставляет поддержку представления пропущенных значений в статистическом смысле, то есть для ситуаций, когда для переменной в наблюдении нет значения, но теоретически существует действительное значение. Пропущенные значения представлены объектом missing, который является единственным экземпляром типа Missing. missing эквивалентен NULL в SQL и NA в R, и ведет себя подобно им в большинстве ситуаций.

Распространение пропущенных значений

Поведение пропущенных значений подчиняется одному основному правилу: пропущенные значения распространяются автоматически при передаче их стандартным операторам и функциям, в частности, математическим функциям. Неопределённость значения одного из операндов вызывает неопределённость результата. На практике это означает, что операция, включающая пропущенное значение, обычно возвращает missing.

julia> missing + 1
missing

julia> "a" * missing
missing

julia> abs(missing)
missing

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

Операторы равенства и сравнения

Стандартные операторы равенства и сравнения следуют правилу распространения, представленному выше: если любой из операндов является missing, результат является missing. Вот несколько примеров.

julia> missing == 1
missing

julia> missing == missing
missing

julia> missing < 1
missing

julia> 2 >= missing
missing

В частности, обратите внимание, что missing == missing возвращает missing, поэтому == нельзя использовать для проверки того, является ли значение пропущенным. Чтобы проверить, является ли x missing, используйте ismissing(x).

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

julia> missing === 1
false

julia> isequal(missing, 1)
false

julia> missing === missing
true

julia> isequal(missing, missing)
true

Оператор isless является ещё одним исключением: missing считается больше любого другого значения. Этот оператор используется функцией sort, которая, следовательно, помещает missing значения после всех других значений.

julia> isless(1, missing)
true

julia> isless(missing, Inf)
false

julia> isless(missing, missing)
false

Логические операторы

Логические (или булевы) операторы |, & и xor являются ещё одним особым случаем, поскольку они распространяют missing значения только тогда, когда это логически необходимо. Для этих операторов неопределенность результата зависит от конкретной операции, следуя хорошо установленным правилам трёхзначной логики, которые также реализуются в SQL и NA в R. Это абстрактное определение на самом деле соответствует относительно естественному поведению, которое лучше всего объясняется на конкретных примерах.

Давайте проиллюстрируем этот принцип на операторе логического "или" |. Следуя правилам булевой логики, если один из операндов является true, значение другого операнда не влияет на результат, который всегда будет true.

julia> true | true
true

julia> true | false
true

julia> false | true
true

Основываясь на этом наблюдении, мы можем заключить, что если один из операндов true, а другой missing, мы знаем, что результат равен true несмотря на неопределённость фактического значения одного из операндов. Если бы мы смогли наблюдать фактическое значение второго операнда, оно могло бы быть только true или false, и в обоих случаях результат был бы true. Таким образом, в этом конкретном случае пропущенность не распространяется.

julia> true | missing
true

julia> missing | true
true

Напротив, если один из операндов false, результат может быть либо true, либо false, в зависимости от значения другого операнда. Поэтому, если этот операнд missing, результат также должен быть missing.

julia> false | true
true

julia> true | false
true

julia> false | false
false

julia> false | missing
missing

julia> missing | false
missing

Поведение оператора логического "и" & аналогично поведению оператора |, с той разницей, что пропущенность не распространяется, когда один из операндов false . Например, когда это относится к первому операнду

julia> false & false
false

julia> false & true
false

julia> false & missing
false

С другой стороны, пропущенность распространяется, когда один из операндов true, например, первый.

julia> true & true
true

julia> true & false
false

julia> true & missing
missing

Наконец, оператор логического "исключающего или" xor всегда распространяет значения missing, поскольку оба операнда всегда влияют на результат. Также обратите внимание, что оператор отрицания ! возвращает missing , когда операнд missing, как и другие унарные операторы.

Операторы управления потоком и короткого замыкания

Операторы управления потоком, включая if, while и тернарный оператор x ? y : z, не допускают пропущенных значений. Это связано с неопределённостью того, будет ли фактическое значение true или false , если мы могли бы его наблюдать, что подразумевает, что нам неизвестно, как программа должна себя вести. Исключение TypeError выбрасывается как только встречается значение missing в этом контексте.

julia> if missing
           println("here")
       end
ERROR: TypeError: non-boolean (Missing) used in boolean context

По той же причине, в отличие от логических операторов, представленных выше, операторы короткого замыкания && и || не допускают значения missing в ситуациях, когда значение операнда определяет, будет ли оцениваться следующий операнд или нет. Например,

julia> missing || false
ERROR: TypeError: non-boolean (Missing) used in boolean context

julia> missing && false
ERROR: TypeError: non-boolean (Missing) used in boolean context

julia> true && missing && false
ERROR: TypeError: non-boolean (Missing) used in boolean context

С другой стороны, никакое исключение не выбрасывается, когда результат может быть определён без значений missing. Это имеет место, когда код выполняет короткое замыкание, прежде чем оценивать операнд missing, и когда операнд missing является последним.

julia> true && missing
missing

julia> false && missing
false

Массивы с пропущенными значениями

Массивы, содержащие пропущенные значения, могут быть созданы, как и другие массивы.

julia> [1, missing]
2-element Array{Union{Missing, Int64},1}:
 1
  missing

Как показывает этот пример, тип элементов таких массивов Union{Missing, T}, а T - тип значений, не являющихся пропущенными. Это просто отражает тот факт, что элементы массива могут быть либо типа T (здесь Int64) либо типа Missing . Такой массив использует эффективное хранение памяти, эквивалентное Array{T} , содержащему фактические значения, вместе с Array{UInt8} , указывающим на тип элемента (т.е., является ли он Missing или T).

Массивы, допускающие пропущенные значения, могут быть созданы с помощью стандартной синтаксической конструкции. Используйте Array{Union{Missing, T}}(missing, dims) для создания массивов, заполненных пропущенными значениями:

julia> Array{Union{Missing, String}}(missing, 2, 3)
2×3 Array{Union{Missing, String},2}:
 missing  missing  missing
 missing  missing  missing

Массив, допускающий missing значения, но не содержащий таких значений, может быть преобразован обратно в массив, не допускающий пропущенных значений, с помощью convert. Если массив содержит missing значения, при преобразовании выбрасывается MethodError.

julia> x = Union{Missing, String}["a", "b"]
2-element Array{Union{Missing, String},1}:
 "a"
 "b"

julia> convert(Array{String}, x)
2-element Array{String,1}:
 "a"
 "b"

julia> y = Union{Missing, String}[missing, "b"]
2-element Array{Union{Missing, String},1}:
 missing
 "b"

julia> convert(Array{String}, y)
ERROR: MethodError: Cannot `convert` an object of type Missing to an object of type String

Пропуск пропущенных значений

Поскольку missing значения распространяются с помощью стандартных математических операторов, функции сокращения возвращают missing при вызове на массивах, содержащих пропущенные значения.

julia> sum([1, missing])
missing

В этой ситуации используйте функцию skipmissing для пропуска пропущенных значений.

julia> sum(skipmissing([1, missing]))
1

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

julia> maximum(skipmissing([3, missing, 2, 1]))
3

julia> mean(skipmissing([3, missing, 2, 1]))
2.0

julia> mapreduce(sqrt, +, skipmissing([3, missing, 2, 1]))
4.146264369941973

Используйте collect для извлечения значений, не являющихся missing и записи их в массив.

julia> collect(skipmissing([3, missing, 2, 1]))
3-element Array{Int64,1}:
 3
 2
 1

Логические операции над массивами

Вышеописанная трёхзначная логика для логических операторов также используется логическими функциями, применяемыми к массивам. Таким образом, тесты на равенство массивов с использованием оператора == возвращают missing всякий раз, когда результат не может быть определён без знания фактического значения missing элемента. На практике это означает, что возвращается missing, если все значения, не являющиеся пропущенными, в сравниваемых массивах равны, но один или оба массива содержат пропущенные значения (возможно, в разных позициях).

julia> [1, missing] == [2, missing]
false

julia> [1, missing] == [1, missing]
missing

julia> [1, 2, missing] == [1, missing, 2]
missing

Как и для отдельных значений, используйте isequal для обработки missing значений как равных другим missing значениям, но отличных от значений, не являющихся пропущенными.

julia> isequal([1, missing], [1, missing])
true

julia> isequal([1, 2, missing], [1, missing, 2])
false

Функции any и all также следуют правилам трёхзначной логики, возвращая missing , когда результат не может быть определён.

julia> all([true, missing])
missing

julia> all([false, missing])
false

julia> any([true, missing])
true

julia> any([false, missing])
missing

© 2009–2019 Jeff Bezanson, Stefan Karpinski, Viral B. Shah, and other contributors
Licensed under the MIT License.
https://docs.julialang.org/en/v0.7.0/manual/missing/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API