Документация Engee

Индексирование

Общие правила

Ниже описываются правила работы getindex, setindex!, view и трансляции с объектами DataFrame, SubDataFrame и DataFrameRow.

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

  • скаляр, далее обозначаемый как col:

    • Symbol;

    • AbstractString;

    • Integer, но не Bool;

  • вектор, далее обозначаемый как cols:

    • вектор значений типа Symbol (необязательно подтип AbstractVector{Symbol});

    • вектор значений типа AbstractString (необязательно подтип AbstractVector{<:AbstractString});

    • вектор значений типа Integer, но не Bool (необязательно подтип AbstractVector{<:Integer});

    • вектор значений типа Bool (должен быть подтипом AbstractVector{Bool});

    • регулярное выражение (развертывается в вектор соответствующих имен столбцов);

    • выражение Not (см. пакет InvertedIndices.jl); Not(idx) выбирает все индексы, которых нет в переданном idx; при передаче в качестве селектора столбцов Not(idx...) эквивалентно Not(Cols(idx...)).

    • выражение Cols (см. пакет DataAPI.jl); Cols(idxs...) выбирает объединение выбранных в idxs столбцов; в частности, Cols() не выбирает ни один столбец, а Cols(:) выбирает все столбцы; особым случаем является Cols(predicate), где predicate — это предикативная функция; в этом случае выбираются столбцы, для имен которых, переданных в predicate в виде строк, возвращается true;

    • выражение Between (см. пакет DataAPI.jl); Between(first, last) выбирает столбцы от first до last включительно;

    • выражение All (см. пакет DataAPI.jl); All() выбирает все столбцы, что равносильно :;

    • литерал двоеточия : (выбирает все столбцы).

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

  • скаляр, далее обозначаемый как row:

    • Integer, но не Bool;

  • вектор, далее обозначаемый как rows:

    • вектор значений типа Integer, но не Bool (необязательно подтип AbstractVector{<:Integer});

    • вектор значений типа Bool (должен быть подтипом AbstractVector{Bool});

    • выражение Not (см. пакет InvertedIndices.jl);

    • литерал двоеточия : (выбирает все строки с копированием);

    • литерал восклицательного знака ! (выбирает все строки без копирования).

Кроме того, допускается индексация объекта AbstractDataFrame с использованием двухмерного объекта CartesianIndex.

В описаниях ниже df представляет объект DataFrame, sdf — объект SubDataFrame, а dfr — объект DataFrameRow.

: всегда расширяется до axes(df, 1) или axes(sdf, 1).

df.col во всех случаях работает так же, как df[!, col], а sdf.col — так же, как sdf[!, col]. Однако в версии Julia 1.6 и более ранних есть одно исключение: df.col .= v и sdf.col .= v выполняют трансляцию на месте, если col имеется в df или sdf и является допустимым именем (эта несогласованность устранена в версии Julia 1.7 и более поздних).

getindex и view

В приведенном ниже списке описывается поведение операций getindex и view в зависимости от типов аргументов.

В частности, явно указывается, копируются ли данные или используются повторно без копирования.

Из соображений производительности при доступе к одной строке row и нескольким столбцам cols объекта DataFrame, SubDataFrame или DataFrameRow посредством getindex или view всегда возвращается DataFrameRow (то есть тип представления).

Вызов getindex для DataFrame:

  • df[row, col] -> значение, содержащееся в строке row в столбце col; то же, что и df[!, col][row];

  • df[CartesianIndex(row, col)] -> равносильно df[row, col];

  • df[row, cols] -> объект DataFrameRow с родительским объектом df;

  • df[rows, col] -> копия вектора df[!, col], которая содержит только те элементы, которые соответствуют выбранным строкам rows; равносильно df[!, col][rows];

  • df[rows, cols] -> объект DataFrame с копиями столбцов cols, которые содержат только те элементы, которые соответствуют выбранным строкам rows;

  • df[!, col] -> вектор, содержащийся в столбце col и возвращаемый без копирования; равносильно df.col, если col — это допустимое имя;

  • df[!, cols] -> создает новый объект DataFrame со столбцами cols без копирования столбцов; равносильно select(df, cols, copycols=false).

Вызов view для DataFrame:

  • @view df[row, col] -> 0-мерное представление df[!, col] по строке row; равносильно view(df[!, col], row);

  • @view df[CartesianIndex(row, col)] -> равносильно @view df[row, col];

  • @view df[row, cols] -> равносильно df[row, cols];

  • @view df[rows, col] -> представление df[!, col] с выбранными строками rows; равносильно view(df[!, col], rows);

  • @view df[rows, cols] -> объект SubDataFrame с выбранными строками rows и родительским объектом df;

  • @view df[!, col] -> представление df[!, col] со всеми строками;

  • @view df[!, cols] -> равносильно @view df[:, cols].

Вызов getindex для SubDataFrame:

  • sdf[row, col] -> значение, содержащееся в строке row в столбце col;

  • sdf[CartesianIndex(row, col)] -> равносильно sdf[row, col];

  • sdf[row, cols] -> объект DataFrameRow с родительским объектом parent(sdf);

  • sdf[rows, col] -> копия sdf[!, col] только с выбранными строками rows; равносильно sdf[!, col][rows];

  • sdf[rows, cols] -> объект DataFrame, содержащий столбцы cols и sdf[rows, col] в качестве вектора для каждого столбца col в cols;

  • sdf[!, col] -> представление из элементов, соответствующих sdf в векторе parent(sdf)[!, col]; равносильно sdf.col, если col — это допустимое имя;

  • sdf[!, cols] -> создает новый объект SubDataFrame со столбцами cols, тем же родительским объектом, что и у sdf, и теми же выбранными строками; равносильно select(sdf, cols, copycols=false).

Вызов view для SubDataFrame:

  • @view sdf[row, col] -> 0-мерное представление df[!, col] по строке row; равносильно view(sdf[!, col], row);

  • @view sdf[CartesianIndex(row, col)] -> равносильно @view sdf[row, col];

  • @view sdf[row, cols] -> объект DataFrameRow с родительским объектом parent(sdf);

  • @view sdf[rows, col] -> представление вектора sdf[!, col] с выбранными строками rows; равносильно view(sdf[!, col], rows);

  • @view sdf[rows, cols] -> объект SubDataFrame с родительским объектом parent(sdf);

  • @view sdf[!, col] -> представление вектора sdf[!, col] со всеми строками;

  • @view sdf[!, cols] -> равносильно @view sdf[:, cols].

Вызов getindex для DataFrameRow:

  • dfr[col] -> значение, содержащееся в столбце col объекта dfr; равносильно dfr.col, если col — это допустимое имя;

  • dfr[cols] -> объект DataFrameRow с родительским объектом parent(dfr).

Вызов view для DataFrameRow:

  • @view dfr[col] -> 0-мерное представление parent(dfr)[DataFrames.row(dfr), col];

  • @view dfr[cols] -> объект DataFrameRow с родительским объектом parent(dfr).

Обратите внимание, что число столбцов в представлениях, создаваемых с селектором столбцов :, изменяется при добавлении, удалении или переименовании столбцов в родительском объекте. Если селектор столбцов отличается от :, то представление ссылается на то количество выбранных столбцов, которое имелось на момент его создания.

setindex!

В приведенном ниже списке описывается поведение операций setindex! в зависимости от типов аргументов.

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

Обратите внимание: если операция setindex! выдает ошибку, целевой фрейм данных может оказаться частично измененным, поэтому дальнейшее его использование небезопасно (правильность длин столбцов сохраняется).

Вызов setindex! для DataFrame:

  • df[row, col] = v -> элементу в столбце col в строке row присваивается значение v на месте;

  • df[CartesianIndex(row, col)] = v -> равносильно df[row, col] = v;

  • df[row, cols] = v -> присваивает значение элементам в строке row в столбцах cols на месте; равносильно dfr = df[row, cols]; dfr[:] = v;

  • df[rows, col] = v -> присваивает значение элементам в строках rows в столбце col на месте; v должно быть вектором AbstractVector; если в качестве rows передан литерал :, а в качестве col —  символ Symbol или строка AbstractString, которых нет в df, в df создается новый столбец, содержащий копию (copy) значения v; равносильно df.col = copy(v), если col — это допустимое имя;

  • df[rows, cols] = v -> присваивает значение элементам в строках rows и столбцах cols на месте; v должно быть матрицей AbstractMatrix или фреймом AbstractDataFrame (в этом случае имена столбцов должны совпадать);

  • df[!, col] = v -> заменяет col на v без копирования (но если v — это диапазон AbstractRange, он преобразуется в Vector); кроме того, если col — это символ Symbol или строка AbstractString, которых нет в df, то в df создается новый столбец, содержащий v; равносильно df.col = v, если col — это допустимое имя; допускается, если ncol(df) == 0 || length(v) == nrow(df);

  • df[!, cols] = v -> заменяет существующие столбцы cols во фрейме данных df с копированием; v должно быть матрицей AbstractMatrix или фреймом AbstractDataFrame (во втором случае имена столбцов должны совпадать);

Вызов setindex! для SubDataFrame:

  • sdf[row, col] = v -> элементу в столбце col в строке row присваивается значение v на месте;

  • sdf[CartesianIndex(row, col)] = v -> равносильно sdf[row, col] = v;

  • sdf[row, cols] = v -> равносильно операции dfr = df[row, cols]; dfr[:] = v на месте;

  • sdf[rows, col] = v -> присваивает значение элементам в строках rows в столбце col на месте; v должно быть абстрактным вектором;

  • sdf[rows, cols] = v -> присваивает значение элементам в строках rows и столбцах cols на месте; v может быть матрицей AbstractMatrix или фреймом AbstractDataFrame (в этом случае имена столбцов должны совпадать);

  • sdf[!, col] = v -> заменяет col на v без копирования; если столбец col имеется в sdf, то отфильтрованные строки в создаваемом векторе заполняются значениями, уже имеющимися в этом столбце, а promote_type используется для определения типа eltype нового столбца; если столбец col отсутствует в sdf, то эта операция допустима только в том случае, если объект sdf был создан с литералом : в качестве селектора столбцов, и в таком случае отфильтрованные строки заполняются значением missing; равносильно sdf.col = v, если col — это допустимое имя; данная операция допустима, если length(v) == nrow(sdf);

  • sdf[!, cols] = v -> заменяет существующие столбцы cols во фрейме данных sdf с копированием; v должно быть матрицей AbstractMatrix или фреймом AbstractDataFrame (во втором случае имена столбцов должны совпадать); отфильтрованные строки в создаваемых векторах заполняются значениями, уже имеющимися в соответствующих столбцах, а promote_type используется для определения типа eltype новых столбцов.

Приведенные выше правила означают, что sdf[:, col] = v — это операция на месте, если col имеется в sdf, поэтому, как правило, она выполняется быстро. С другой стороны, при использовании sdf[!, col] = v или sdf.col = v в памяти всегда размещается новый вектор, что требует больше вычислительных ресурсов.

Вызов setindex! для DataFrameRow:

  • dfr[col] = v -> элементу в столбце col в строке row присваивается значение v на месте; равносильно dfr.col = v, если col — это допустимое имя;

  • dfr[cols] = v -> элементам в столбцах cols объекта dfr присваиваются значения элементов v на месте; v может иметь один из следующих типов: 1) кортеж Tuple или массив AbstractArray, количество элементов которого должно быть равно length(dfr); 2) словарь AbstractDict; в этом случае имена должны совпадать; 3) кортеж NamedTuple или объект DataFrameRow; в этом случае имена и порядок столбцов должны совпадать.

Трансляция

Для объектов AbstractDataFrame действуют следующие правила трансляции.

  • AbstractDataFrame ведет себя при трансляции как двухмерная коллекция, совместимая с матрицами.

  • Если объект AbstractDataFrame участвует в трансляции, то результатом всегда будет DataFrame. В этом случае запрошенная операция трансляции всегда возвращает объект ровно с двумя измерениями. Исключением является ситуация, когда AbstractDataFrame используется только в качестве источника присваивания с трансляцией объекту с размерностью более двух.

  • Если в трансляции участвует несколько объектов AbstractDataFrame, то они должны иметь идентичные имена столбцов.

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

Трансляция DataFrameRow в настоящее время не допускается (что согласуется с NamedTuple).

Объектам AbstractDataFrame и DataFrameRow значения можно присваивать с помощью оператора .=. При такой операции объект AbstractDataFrame считается двухмерным, а DataFrameRow — одномерным.

Приведенное выше правило означает, что, как и в случае с одномерными объектами в модуле Base (например, векторами), объект DataFrameRow считается столбцовым.

Дополнительные правила

  • В синтаксических конструкциях df[CartesianIndex(row, col)] .= v и df[row, col] .= v значение v транслируется в содержимое df[row, col] (это согласуется с поведением, принятым в модуле Julia Base).

  • В синтаксических конструкциях df[row, cols] .= v присваивание значения объекту df выполняется на месте.

  • В синтаксических конструкциях df[rows, col] .= v и df[rows, cols] .= v присваивание значения объекту df выполняется на месте. Если в качестве rows передан литерал :, а в качестве col — символ Symbol или строка AbstractString, которые отсутствуют в df, то новый столбец размещается в памяти и добавляется. Длина столбца всегда равна nrow(df) перед присваиванием.

  • В синтаксической конструкции df[!, col] .= v столбец col заменяется новым размещенным в памяти вектором. Если в качестве col передан символ Symbol или строка AbstractString, которые отсутствуют в df, то новый столбец размещается в памяти и добавляется. Длина столбца всегда равна nrow(df) перед присваиванием.

  • Синтаксическая конструкция df[!, cols] .= v заменяет существующие столбцы cols во фрейме данных df новыми размещенными в памяти векторами.

  • Синтаксическая конструкция df.col .= v в настоящее время выполняет присваивание значения на месте существующему вектору df.col. Такое поведение считается устаревшим, и в будущем в памяти будет размещаться новый столбец. Начиная с версии Julia 1.7, если :col отсутствует в df, то в df создается новый столбец.

  • В синтаксических конструкциях sdf[CartesianIndex(row, col)] .= v, sdf[row, col] .= v и sdf[row, cols] .= v присваивание значения объекту sdf выполняется на месте.

  • В синтаксических конструкциях sdf[rows, col] .= v и sdf[rows, cols] .= v присваивание значения объекту sdf выполняется на месте. Если в качестве rows передан литерал :, а в качестве col — символ Symbol или строка AbstractString, ссылающиеся на столбец, которого нет в sdf, и объект sdf был создан с литералом : в качестве селектора столбцов, то новый столбец размещается в памяти и добавляется. Отфильтрованные строки заполняются значением missing.

  • В синтаксической конструкции sdf[!, col] .= v столбец col заменяется новым размещенным в памяти вектором. Отфильтрованные строки заполняются значениями, уже имеющимися в столбце col. Если в качестве col передан символ Symbol или строка AbstractString, ссылающиеся на столбец, которого нет в sdf, и объект sdf был создан с литералом : в качестве селектора столбцов, то новый столбец размещается в памяти и добавляется. В этом случае отфильтрованные строки заполняются значением missing.

  • Синтаксическая конструкция sdf[!, cols] .= v заменяет существующие столбцы cols во фрейме данных sdf новыми размещенными в памяти векторами. Отфильтрованные строки заполняются значениями, уже имеющимися в cols.

  • Синтаксическая конструкция sdf.col .= v в настоящее время выполняет присваивание значения на месте существующему вектору sdf.col. Такое поведение считается устаревшим, и в будущем в памяти будет размещаться новый столбец. Начиная с версии Julia 1.7, если :col отсутствует в sdf, то в sdf создается новый столбец, если объект sdf был создан с литералом : в качестве селектора столбцов.

  • Синтаксическая конструкция dfr.col .= v допустима и выполняет присваивание на месте значению, извлеченному с помощью dfr.col.

Обратите внимание, что синтаксические конструкции sdf[!, col] .= v и sdf[!, cols] .= v недопустимы, так как объект sdf можно изменять только на месте.

При индексировании столбцов по именам типа Symbol или AbstractString в cols порядок столбцов в операции определяется согласно порядку имен.

Индексирование объектов GroupedDataFrame

Объект GroupedDataFrame может вести себя как AbstractVector или AbstractDict в зависимости от типа используемого индекса. Целочисленные индексы (или их массивы) приводят к векторному индексированию, а кортежи Tuples и NamedTuple — к индексированию наподобие словарей. Нечто среднее представляет собой тип GroupKey, возвращаемый keys(::GroupedDataFrame). Он ведет себя так же, как NamedTuple, но по производительности сопоставим с целочисленным индексированием.

Элементами фрейма GroupedDataFrame являются объекты SubDataFrame родительского объекта.

  • gd[i::Integer] -> возвращает i-ю группу.

  • gd[key::NamedTuple] -> возвращает группу, соответствующую предоставленным значениям столбцов группировки. Поля NamedTuple должны соответствовать столбцам группировки, переданным в groupby (включая их порядок).

  • gd[key::Tuple] -> аналогично предыдущему вызову, но без указания имен в key.

  • get(gd, key::Union{Tuple, NamedTuple}, default) -> возвращает группу для ключа key или default, если такой группы нет.

  • gd[key::GroupKey] -> возвращает группу, соответствующую GroupKey key (один из элементов вектора, возвращаемого keys(::GroupedDataFrame)). Выполняется почти так же быстро, как целочисленное индексирование.

  • gd[a::AbstractVector] -> выбирает несколько групп и возвращает их в новом объекте GroupedDataFrame. Группы могут выбираться по целочисленной позиции с помощью массива значений типа Integer или Bool, похожего на обычный массив. Массив может также содержать ключи любого из типов, поддерживаемых при индексировании словарей (GroupKey, Tuple или NamedTuple). Выбираемые группы должны быть уникальными. Разные типы индексов нельзя использовать вместе.

  • gd[n::Not] -> любой из приведенных выше типов, заключенный в Not. Результатом будет новый объект GroupedDataFrame, содержащий все группы в gd, которые не выбираются заключенным в Not индексом.

Общий API для типов, определенных в DataFrames.jl

В этой таблице представлены типы значений, которые возвращаются при вызове names, propertynames, keys, length и ndims для типов, доступных пользователю в пакете DataFrames.jl:

Тип names propertynames keys length ndims

AbstractDataFrame

Vector{String}

Vector{Symbol}

не определено

не определено

2

DataFrameRow

Vector{String}

Vector{Symbol}

Vector{Symbol}

Int

1

DataFrameRows

Vector{String}

Vector{Symbol}

вектор Int

Int

1

DataFrameColumns

Vector{String}

Vector{Symbol}

Vector{Symbol}

Int

1

GroupedDataFrame

Vector{String}

кортеж полей

GroupKeys

Int

1

GroupKeys

не определено

кортеж полей

вектор Int

Int

1

GroupKey

Vector{String}

Vector{Symbol}

Vector{Symbol}

Int

1

Кроме того, для приведенных выше типов T (AbstractDataFrame, DataFrameRow, DataFrameRows, DataFrameColumns, GroupedDataFrame, GroupKeys, GroupKey) определены следующие методы:

  • size(::T) возвращает кортеж Tuple значений типа Int.

  • size(::T, ::Integer) возвращает Int.

  • axes(::T) возвращает кортеж Tuple векторов типа Int.

  • axes(::T, ::Integer) возвращает вектор типа Int для допустимого измерения (кроме объектов DataFrameRows и GroupKeys, для которых Base.OneTo(1) также возвращается для измерения выше допустимого, поскольку они имеют тип AbstractVector).

  • firstindex(::T) возвращает 1 (кроме объекта AbstractDataFrame, для которого этот метод не определен).

  • firstindex(::T, ::Integer) возвращает 1 для допустимого измерения (кроме объектов DataFrameRows и GroupKeys, для которых 1 также возвращается для измерения выше допустимого, поскольку они имеют тип AbstractVector).

  • lastindex(::T) возвращает Int (кроме объекта AbstractDataFrame, для которого этот метод не определен).

  • lastindex(::T, ::Integer) возвращает Int для допустимого измерения (кроме объектов DataFrameRows и GroupKeys, для которых 1 также возвращается для измерения выше допустимого, поскольку они имеют тип AbstractVector).