Взятие среза data.table с последовательностью индексов (строка, столбец)

У меня есть data.table, похожий на показанный ниже.

tab <- data.table(a = c(NA, 42190, NA), b = c(42190, 42190, NA), c = c(40570, 42190, NA))
tab
       a     b     c
1:    NA 42190 40570
2: 42190 42190 42190
3:    NA    NA    NA

После указания вектора индексов строк и вектора индексов столбцов я хотел бы, чтобы возвращаемый вектор содержал точки в tab, соответствующие указанному вектору индексов строк и индексов столбцов.

Например, предположим, что я хочу получить диагональные элементы в tab. Я бы указал два вектора,

ri <- 1:3
ci <- 1:3

и некоторая функция function(ri, ci, tab) вернет диагональные элементы tab.

Если бы tab был data.frame, я бы сделал то, что ниже,

as.data.frame(tab)[cbind(ri, ci)]

но я хотел бы избежать синтаксиса data.frame. Я также хотел бы избежать цикла for, поскольку он имеет тенденцию быть медленным.


person Joshua Daly    schedule 01.06.2018    source источник
comment
может переплавить в длинный формат и установить ключ?   -  person chinsoon12    schedule 01.06.2018
comment
Вот аналогичные вопросы для поиска матрицы с вектором строк, индексов столбцов: indexes">Подстановка матрицы с помощью вектора индексов, Использовать индексы в векторе для извлечения элементов из матрицы   -  person smci    schedule 01.06.2018
comment
Спасибо @chinsoon12. В идеале решение не должно преобразовываться и должно быть прямым индексом.   -  person Joshua Daly    schedule 01.06.2018
comment
Если вы имеете дело со всеми числовыми данными, вам лучше с самого начала работать с matrix. Метод индексации, который вы показываете на матрице, очень быстрый.   -  person thelatemail    schedule 01.06.2018
comment
согласен с @thelatemail, что для размера данных и количества вызовов подмножества, вероятно, быстрее использовать матрицу. но я все еще верю, что будет точка пересечения, когда data.table будет быстрее.   -  person chinsoon12    schedule 01.06.2018
comment
@chinsoon12: конечно; но если матрица подходит для задачи ОП, они могут сделать ее основной структурой данных. Если у кого-то есть энергия, чтобы построить его, мне любопытно, как выглядит график DT против матрицы против матрицы для индексации nxn с n произвольными индексами (строка, столбец).   -  person smci    schedule 01.06.2018
comment
Я бы назвал это Выбор среза DT/матрицы с последовательностью индексов (строка,столбец)   -  person smci    schedule 03.06.2018
comment
Спасибо @smci, я отредактирую это.   -  person Joshua Daly    schedule 03.06.2018


Ответы (2)


Есть более быстрый способ сделать это, чем приведение к матрице или data.frame. Просто используйте функцию [data.frame.

`[.data.frame`( tab,  cbind(ri,ci) )
[1]    NA 42190    NA

Это функциональный синтаксис для функции [.data.frame.

person IRTFM    schedule 05.03.2019
comment
Потрясающий. Можете ли вы объяснить в своем ответе, почему [.data.frame изначально работает с таблицей данных, и ссылку на его документ? - person smci; 05.03.2019
comment
Функции R отправляются по классу их первого аргумента. Запустите class(DT), и вы получите [1] "data.table" "data.frame". Поскольку функция [ является общей и имеет метод фрейма данных, то есть функцию {.data.frame. Таким образом, интерпретатор передает объект data.table в код этой функции, а не в [.data.table. Посмотрите на вывод из methods([) - person IRTFM; 05.03.2019

(ОБНОВЛЕНИЕ: ответ @42- с использованием [.data.frame лучше всего. Но вот мой предыдущий ответ)

as.matrix(tab)[cbind(ri, ci)]

будет быстрее и эффективнее использовать память, чем melt.

Я не вижу причин, по которым вы не объявляете свой DT как матрицу, как рекомендует @thelatemail. Это тот случай, когда синтаксис DT не так эффективен, как матричный.

(Для экономии памяти с большими DT в data.table есть команды setDF/setDT, позволяющие преобразовывать в/из DF/DT без копирования, но я не знаю, что у него есть эквивалент для матрицы. Если это то, что люди делают много из, это могло бы сделать хороший запрос расширения для DT.

Для действительно больших размеров вы можете изучить пакет Matrix sparse-matrix) или разбить свой данные или использовать структуры данных на диске.)

person smci    schedule 01.06.2018
comment
Абсолютно. матричная индексация — одна из самых недооцененных функций R imho. - person thelatemail; 01.06.2018
comment
Спасибо @smci. tab происходит от подмножества data.table, поэтому я не использую матрицу для начала. Быстро ли перейти от data.table к матрице? - person Joshua Daly; 01.06.2018
comment
@JoshuaDaly: as.matrix() должно быть довольно быстро, насколько велики ваши размеры? Если что-то станет действительно большим, вы можете изучить форматы разреженной матрицы Matrix, разбить данные на фрагменты или использовать структуры данных на диске. - person smci; 01.06.2018
comment
Спасибо @smci, к счастью, он не слишком большой (8 x 4 data.table), но я буду выполнять операцию много раз, поэтому я хотел бы избежать как можно больших накладных расходов. Но ваш ответ превосходен и охватывает, что делать, когда данных станет больше, и я отмечу его как ответ. - person Joshua Daly; 01.06.2018
comment
Прохладно. Взгляните на пакет Matrix - person smci; 01.06.2018
comment
Принуждение — ненужный шаг. Оставьте его как data.table (который наследуется от data.frame) и используйте функцию, предназначенную для data.frames. - person IRTFM; 05.03.2019
comment
@42- Отлично, не знал о [.data.frame до сих пор. - person smci; 05.03.2019