Написание функции, которая принимает вектор в качестве входных данных, отбрасывает нежелательные значения, удаляет дубликаты и возвращает соответствующие индексы исходного вектора

#r #function #vector #duplicates

#r #функция #вектор #дубликаты

Вопрос:

Я пытаюсь написать функцию, которая принимает вектор и подмножествует его в соответствии с несколькими шагами:

  1. Отбрасывает любые нежелательные значения
  2. Удаляет дубликаты.
  3. Возвращает индексы исходного вектора после учета шагов (1) и (2).

Например, при наличии следующего входного вектора:

 vec_animals lt;- c("dog", "dog", "dog", "dog", "cat", "dolphin", "dolphin")  

и

 throw_away_val lt;- "cat"  

Я хочу, чтобы моя функция get_indexes(x = vec_animals, y = throw_away_val) возвращалась:

 # [1] 1 6 # `1` is the index of the 1st unique ("dog") in `vec_animals`, `6` is the index of the 2nd unique ("dolphin")  

Еще один пример

 vec_years lt;- c(2003, 2003, 2003, 2007, 2007, 2011, 2011, 2011) throw_away_val lt;- 2003  

Возврат:

 # [1] 4 6 # `4` is the position of 1st unique (`2007`) after throwing away unwanted val; `6` is the position of 2nd unique (`2011`).  

Моя первая попытка

Следующая функция возвращает индексы, но не учитывает дубликаты

 get_index lt;- function(x, throw_away) {  which(x != throw_away) }  

который затем возвращает индексы оригинала vec_animals , такие как:

 get_index(vec_animals, "cat") #gt; [1] 1 2 3 4 6 7  

Если мы используем этот вывод для подмножества vec_animal , мы получим:

 vec_animals[get_index(vec_animals, "cat")] #gt; [1] "dog" "dog" "dog" "dog" "dolphin" "dolphin"  

Вы могли бы предложить оперировать этим выводом, например:

 vec_animals[get_index(vec_animals, "cat")] |gt; unique() #gt; [1] "dog" "dolphin"  

Но нет, мне нужно get_index() сразу же вернуть правильные индексы (в данном случае 1 и 6 ).


Редактировать


Соответствующая процедура, в которой мы можем получить индексы первых появлений дубликатов, снабжена

 library(bit64)  vec_num lt;- as.integer64(c(4, 2, 2, 3, 3, 3, 3, 100, 100)) unipos(vec_num) #gt; [1] 1 2 4 8  

Или в более общем плане

 which(!duplicated(vec_num)) #gt; [1] 1 2 4 8  

Такие решения были бы великолепны, если бы не нужно было также выбрасывать ненужные ценности.

Ответ №1:

Попробуй:

 get_index lt;- function(x, throw_away) {  which(!duplicated(x) amp; x!=throw_away)  }  gt; get_index(vec_animals, "cat") [1] 1 6  

Комментарии:

1. Спасибо. вы можете изменить значение x!=throw_away на !(x %in% throw_away) , если хотите отказаться от более чем одного значения

2. Было бы неплохо (хотя и не обязательно), если бы вы могли подробнее рассказать о механизме, по которому работает ваше решение. Я понимаю, что это связано с R векторизованными операциями, но у меня нет большой интуиции, кроме этого.

3. Посмотрите, как работают отдельные компоненты. duplicated(x) задает вектор логических значений, соответствующий тому, является ли каждый из элементов x дубликатом предыдущего значения или нет. x!=throwaway также является вектором логических значений, соответствующим тому, следует ли выбрасывать каждый элемент. which затем возвращает индексы элементов x , которые удовлетворяют обоим условиям (т. е. оба вектора являются TRUE ).

4. Значит, первое ! отрицает все amp; выражение целиком? Или это только отрицает duplicates(x) ?

5. Первое ! только отрицает duplicated(x) . Я мог бы использовать скобки, чтобы сделать это более ясным.

Ответ №2:

Вот простая функция, написанная самостоятельно, которая предоставляет необходимую информацию.

 vec_animals lt;- c("dog", "dog", "dog", "dog", "cat", "dolphin", "dolphin")  get_indexes lt;- function(x, throw_away){  elements lt;- (unique(x))[(unique(x)) != throw_away]  index lt;- lapply(1:length(elements), function(i) {which(x %in% elements[i]) })  index2return lt;- c()  for (j in 1:length(index)) {  index2return lt;- c(index2return, min(index[[j]]))  }  return(index2return) }  get_indexes(x = vec_animals, throw_away = "cat") [1] 1 6  

Ответ №3:

Мой подход :

 vec_animals lt;- c("dog", "dog", "dog", "dog", "cat", "dolphin", "dolphin") throw_away_val lt;- "cat"  my_function lt;- function(x, y) { my_df lt;- data.frame("Origin" = x,  "Position" = seq.int(from = 1, to = length(x), by = 1),  stringsAsFactors = FALSE) my_var lt;- which(my_df$Origin %in% y) if (length(my_var)) { my_df lt;- my_df[-my_var,] } my_df lt;- my_df[!duplicated(my_df$Origin),] return (my_df) }  my_df lt;- my_function(vec_animals, throw_away_val)