Spec-Zone.ru › Julia 1.4

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

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

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

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

julia> missing + 1
missing

julia> "a" * missing
missing

julia> abs(missing)
missing

Поскольку missing является обычным объектом Julia, это правило распространения работает только для функций, которые выбрали реализацию этого поведения. Это может быть достигнуто либо с помощью определенного метода для аргументов типа Missing, либо просто путем принятия аргументов этого типа и передачи их функциям, которые распространяют их (например, стандартные операторы). Пакеты должны учитывать, имеет ли смысл распространять пропущенные значения при определении новых функций, и определять соответствующие методы, если это необходимо. Передача значения 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 только тогда, когда это логически необходимо. Для этих операторов неопределенность результата зависит от конкретной операции, следуя хорошо известным правилам трехзначной логики, которые также реализованы в NULL в 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> x = skipmissing([3, missing, 2, 1])
Base.SkipMissing{Array{Union{Missing, Int64},1}}(Union{Missing, Int64}[3, missing, 2, 1])

julia> maximum(x)
3

julia> mean(x)
2.0

julia> mapreduce(sqrt, +, x)
4.146264369941973

Объекты, созданные с помощью вызова skipmissing на массиве, могут быть индексированы с помощью индексов из родительского массива. Индексы, соответствующие пропущенным значениям, недействительны для этих объектов, и при попытке их использования возникает ошибка (они также пропускаются keys и eachindex)

julia> x[1]
3

julia> x[2]
ERROR: MissingException: the value at index (2,) is missing
[...]

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

julia> findall(==(1), x)
1-element Array{Int64,1}:
 4

julia> findfirst(!iszero, x)
1

julia> argmax(x)
1

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

julia> collect(x)
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–2020 Jeff Bezanson, Stefan Karpinski, Viral B. Shah, and other contributors
Licensed under the MIT License.
https://docs.julialang.org/en/v1.4.2/manual/missing/

Spec-Zone.ru

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