Мой вопрос связан с назначением по ссылке, а не копированием в data.table
. Я хочу знать, если можно удалить строки по ссылке, аналогично
DT[ , someCol := NULL]
Я хочу знать о
DT[someRow := NULL, ]
Я думаю, есть веская причина, почему эта функция не существует, поэтому, возможно, вы могли бы просто указать на хорошую альтернативу обычному подходу к копированию, как показано ниже. В частности, перейдя с моей любимой из примера (data.table),
DT = data.table(x = rep(c("a", "b", "c"), each = 3), y = c(1, 3, 6), v = 1:9)
# x y v
# [1,] a 1 1
# [2,] a 3 2
# [3,] a 6 3
# [4,] b 1 4
# [5,] b 3 5
# [6,] b 6 6
# [7,] c 1 7
# [8,] c 3 8
# [9,] c 6 9
Скажем, я хочу удалить первую строку из этого data.table. Я знаю, что могу это сделать:
DT <- DT[-1, ]
но часто мы можем захотеть избежать этого, потому что мы копируем объект (а это требует около 3 * N памяти, если N object.size(DT)
, как указано здесь . Теперь я обнаружил set(DT, i, j, value)
. Я знаю, как установить конкретные значения (как здесь: установить все значения в строках 1 и 2 и столбцах 2 и 3 равны нулю)
set(DT, 1:2, 2:3, 0)
DT
# x y v
# [1,] a 0 0
# [2,] a 0 0
# [3,] a 6 3
# [4,] b 1 4
# [5,] b 3 5
# [6,] b 6 6
# [7,] c 1 7
# [8,] c 3 8
# [9,] c 6 9
Но как я могу стереть первые два ряда, скажем? дела
set(DT, 1:2, 1:3, NULL)
устанавливает весь DT в NULL.
Мои знания SQL очень ограничены, так что вы, ребята, скажите мне: данный data.table использует технологию SQL, есть ли эквивалент команды SQL
DELETE FROM table_name
WHERE some_column=some_value
в data.table?
источник
data.table()
использует технологию SQL настолько, насколько можно провести параллель между различными операциями в SQL и различными аргументами adata.table
. Для меня ссылка на «технологию» в некоторой степени подразумевает, что онаdata.table
находится где-то на вершине базы данных SQL, что не соответствует AFAIK.DT[ , keep := .I > 1]
, затем подмножество для последующих операций:DT[(keep), ...]
возможно, дажеsetindex(DT, keep)
скорость этого подмножества. Не панацея, но стоит рассмотреть в качестве варианта дизайна в вашем рабочем процессе - вы действительно хотите удалить все эти строки из памяти , или вы бы предпочли исключить их? Ответ зависит от варианта использования.Ответы:
Хороший вопрос.
data.table
не может удалить строки по ссылке.data.table
Можно добавлять и удалять столбцы по ссылке, поскольку, как вы знаете, он перераспределяет вектор указателей столбцов. План состоит в том, чтобы сделать что-то подобное для рядов и позволить быстроinsert
иdelete
. Удаление строки будет использоватьсяmemmove
в C для составления бюджета элементов (в каждом столбце) после удаленных строк. Удаление строки в середине таблицы будет по-прежнему весьма неэффективным по сравнению с базой данных хранилища строк, такой как SQL, которая больше подходит для быстрой вставки и удаления строк, где бы эти строки не находились в таблице. Но все же, это было бы намного быстрее, чем копировать новый большой объект без удаленных строк.С другой стороны, поскольку векторы столбцов будут перераспределены, строки могут быть вставлены (и удалены) в конце , немедленно; например, растущий временной ряд.
Это подано как проблема: удалить строки по ссылке .
источник
fread
первым. После этого это довольно высоко.DT[b<8 & a>3]
возвращает новый data.table. Мы хотели бы добавитьdelete(DT, b>=8 | a<=3)
иDT[b>=8 | a<=8, .ROW:=NULL]
. Преимущество последнего будет сочетаться с другими функциями,[]
такими как номера строкi
, объединениеi
иroll
извлечение выгоды от[i,j,by]
оптимизации.подход, который я использовал для того, чтобы использование памяти было похоже на удаление на месте, состоит в том, чтобы подбирать столбец за раз и удалять. не так быстро, как правильное решение C memmove, но использование памяти - это все, что меня волнует. что-то вроде этого:
источник
memmove
секунд, чтобы сократить расходы, но это нормально.DT[, col:= NULL, with = F]
вset(DT, NULL, col, NULL)
Вот рабочая функция, основанная на ответе @ vc273 и отзывах @ Frank.
И пример его использования:
Где «dat» - это таблица данных. На моем ноутбуке удаление 14 тысяч строк из 1,4 миллионов строк занимает 0,25 секунды.
PS. Так как я новичок в SO, я не могу добавить комментарий в ветку @ vc273 :-(
источник
Вместо этого или пытаясь установить значение NULL, попробуйте установить значение NA (соответствует типу NA для первого столбца).
источник
Тема по-прежнему интересна многим людям (включая меня).
Что об этом? Я использовал
assign
для заменыglovalenv
и код, описанный ранее. Было бы лучше захватить исходную среду, но, по крайней мере,globalenv
она эффективна для памяти и действует как изменение по ссылке.источник
address(DT); delete(DT, 3); address(DT)
), хотя это может быть эффективным в некотором смысле.Вот несколько стратегий, которые я использовал. Я считаю, что функция .ROW может появиться. Ни один из этих подходов ниже не является быстрым. Это некоторые стратегии, которые выходят за рамки подмножеств или фильтрации. Я пытался думать как dba, просто пытаясь очистить данные. Как отмечено выше, вы можете выбрать или удалить строки в data.table:
Примечание: .SD создает подмножество исходных данных и позволяет вам проделать немалую работу в j или последующих data.table. См. Https://stackoverflow.com/a/47406952/305675 . Здесь я упорядочил свои ирисы по длине Sepal, взял как минимум заданную длину Sepal.Length, выбрал три первых (по длине Sepal) всех видов и вернул все сопутствующие данные:
Подходы прежде всего переупорядочивают таблицу данных последовательно при удалении строк. Вы можете транспонировать таблицу data.table и удалять или заменять старые строки, которые теперь являются транспонированными столбцами. При использовании ': = NULL' для удаления транспонированной строки также удаляется имя следующего столбца:
Когда вы перемещаете data.frame обратно в data.table, вы можете захотеть переименовать исходный data.table и восстановить атрибуты класса в случае удаления. Применение ": = NULL" к теперь транспонированному data.table создает все классы символов.
Вы можете просто удалить дубликаты строк, которые вы можете сделать с ключом или без него:
Также можно добавить инкрементный счетчик с помощью «.I». Затем вы можете найти дублированные ключи или поля и удалить их, удалив запись со счетчиком. Это вычислительно дорого, но имеет некоторые преимущества, так как вы можете напечатать строки, которые нужно удалить.
Вы также можете просто заполнить строку 0 или NA, а затем использовать запрос i, чтобы удалить их:
источник
t
на data.frame обычно не очень хорошая идея; проверьте,str(m_iris)
что все данные стали строкой / символом. Кстати, вы также можете получить номера строк с помощьюd_iris[duplicated(Key), which = TRUE]
без создания счетчика столбца.