2016-01-06 5 views
4

Я знаю, что это может быть выполнено с помощью цикла for, но я уверен, что в конструкции data.table есть более элегантное решение.Создайте новую переменную со ссылкой из другой data.table

У меня есть две таблицы данных, и будет использовать «ирис», чтобы проиллюстрировать мою проблему:

library("data.table") 
A <- as.data.table(iris)      #primary data table 
B <- A[Sepal.Width > 3, .N, by = Species]  #count from A meeting condition 

head(A, 3) 
#  Sepal.Length Sepal.Width Petal.Length Petal.Width Species 
#1:   5.1   3.5   1.4   0.2  setosa 
#2:   4.9   3.0   1.4   0.2  setosa 
#3:   4.7   3.2   1.3   0.2  setosa 

B 
#  Species N 
#1:  setosa 42 
#2: versicolor 8 
#3: virginica 17 

Я хотел бы, чтобы добавить новую переменную B, которая является просто часть набора данных, что B представляет , то есть для первой строки на выходе будет что-то вроде:

B[, Proportion := N/nrow(A[Species == "setosa"])] 

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

Это итерация, которая ускользает от меня (хотя я чувствую, что это связано с ключом таблицы данных)?); очень ценю любую помощь!

ответ

4

Я хотел бы подойти к этому следующим образом:

A <- as.data.table(iris) 
B <- A[Sepal.Width > 3, .N, by = .("spec" = Species)] 

B[, Proportion := N/nrow(A[Species == spec]), by = spec] 

, который дает:

> B 
     spec N Proportion 
1:  setosa 42  0.84 
2: versicolor 8  0.16 
3: virginica 17  0.34 

Объяснение:

  • переименованием Species столбец spec, предотвратить R & data.table из не зная, какой столбец взять для расчета Proportion.
  • Использование by = spec позаботится о том, чтобы правильный spec использовался в A[Species == spec].
+0

Jaap это отлично работало на моих (гораздо больших) таблицах данных. Я отметил это как есть, но не могли бы вы немного объяснить это словами? Я полагаю, что ваше назначение B отличается тем, что вы присвоили ему другое имя столбца/переменной («spec» v. «Species»), которое будет использоваться в индексе для Пропорции, да? .. почему «нужно»? хоть?Я тестировал без него и видел, что результаты были неправильными, но я не могу понять, как это исправить. – daRknight

+0

@daRknight обновлено с кратким объяснением, HTH – Jaap

1

Один вопрос много решений ;-)

library("data.table") 
A <- as.data.table(iris)      #primary data table 

B <- A[, .(group.count = nrow(.SD[Sepal.Width > 3]), total.count = .N), by = Species] 
     [, Proportion := group.count/total.count] 

# Just to validate the total counts: 
A[, .N, by = Species][] 

Результат:

 Species group.count total.count Proportion 
1:  setosa   42   50  0.84 
2: versicolor   8   50  0.16 
3: virginica   17   50  0.34 

Как это работает:

Группа по видам, а затем подсчитать для каждой группы (содержащихся в переменной .SD = «вспомогательные данные» текущей группы), в результате чего строки каждой группы снова фильтруются для подсчета только соответствующих. Затем я использую результат во втором «цепном» data.table запросе (во вторых квадратных скобках) для вычисления пропорций.

Оператор .() - это таблица данных. Таблица abrev. для функции конструктора списка list() и требуется, поскольку я возвращаю более одного столбца.

Оператор := создает новый столбец по ссылке (= без копирования всей таблицы данных = очень быстро).

+0

_Один вопрос много решений; -) _ не мог согласиться больше! Мне нравится это также, поскольку он разъясняет использование '.SD', я предпочитаю только оригинальный ответ, поскольку он избегает дополнительного столбца - в этом примере это не так заметно, но с набором данных, с которым я работаю, уже для меня субоптимально, чтобы я мог следить за всем. Тем не менее, я благодарен вам за эту версию. – daRknight

+0

@daRknight Не могли бы вы дать нам сравнение производительности обоих решений (давайте также учиться на вашем опыте :-)? –

Смежные вопросы