2012-06-26 5 views
0

В R, возможно ли выполнить «немедленное» логическое индексирование на выходе функции?R немедленное (с каналом?) Логическое индексирование на выходе функции?

Чтобы прояснить этот несколько неясный вопрос, вот маленький повседневный пример, который, как я уверен, многие люди встретили раньше. Предположим, что мы имеем вектор «данных», как показано в следующем:

data <- c(1,1,3,5,6,6,8,10,14,15,15,20) 

Если мы теперь применить функцию «Tabulate» к этому вектору, то результат будет:

tabulate(data) 
[1] 2 0 1 0 1 2 0 1 0 1 0 0 0 1 2 0 0 0 0 1 

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

tabulate(data)[tabulate(data) != 0] 
[1] 2 1 1 2 1 1 1 2 1 

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

Мой вопрос сейчас просто: делает простой, более элегантный (синтаксический) обходной путь для таких проблем существует? что-то вроде «волшебной» функции direct.index, что делает работу? как это так,

direct.index(tabulate.data, condition='!= 0') 

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

Конкретная проблема с нулевым удалением из «табулированных» res здесь даны простоты; на самом деле, я почесал голову об этом в самых разных ситуациях. Возможно, у меня также есть некоторые основные заблуждения относительно R ...

Кстати, я изучил «подмножество», но это, похоже, не то, что я ищу.

ответ

2

версия функции, написанной рукой

direct.index <- function(x, condition, value){ 
    index <- eval(call(condition, x, value)) 
    x[which(index)] 
} 

direct.index(tabulate(data), '!=', 0) 
## [1] 2 1 1 2 1 1 1 2 1 

Но, я думаю, что вы ищете функции table

table(data) 
## data 
## 1 3 5 6 8 10 14 15 20 
## 2 1 1 2 1 1 1 2 1 
+1

+1 Я редактировал вашу функцию, чтобы сделать его более очевидным, что она работает в общем, не только для табуляции (т.е. только переименованных объектов). – Andrie

+0

Спасибо за ответ! Я просмотрел таблицу, которая является «правильной» вещью для использования в приведенном выше примере. Но это также быстрее? Я думал, что он также внутренне использует «tabulate», а затем просто делает «уникальный» вызов и ненулевое индексирование автоматически. Кроме того, предоставленная вами ручная функция является оберткой для проблемы, о которой я говорил. Я предполагаю, что нет способа прямого сброса значений, которые я не хочу? Скажем, я «табулирую» на большой вектор (10^6 элементов или более) с большим диапазоном (vaules в [1, 10^9], например). – Lymond