Удаление множества записей из вектора строк по имени - PullRequest
0 голосов
/ 18 ноября 2018

Я хотел бы удалить около 100 записей в векторе с 500 именами столбцов, а затем использовать этот вектор для приведения строк матрицы (прогнозирования) m к нулю.

В качестве очень простого примерамоего фрейма данных:

A 1 2 3
B 1 2 3
C 1 2 3
D 1 2 3
E 1 2 3
F 1 2 3
G 1 2 3
H 1 2 3
I 1 2 3
J 1 2 3

Сначала я помещаю имена столбцов в вектор:

x <- colnames(df) # x <- c("A","B","C","D","E","F","G,"H","I","J")

Допустим, я хотел бы удалить B до D, F и G до I (которые на самом деле около 100 переменных, разбросанных по вектору, для которых я не знаю их индекса).Я хотел бы сделать что-то вроде:

*remove <- c(B:D, F, G:I)* # This does now work obviously
x [! x %in% remove]

Что бы оставить меня с вектором x следующим образом:

A
E
J

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

m[x,] <- 0

Создание следующего вывода:

  A B C D E F G H
A 1 0 1 0 1 0 1 0
B 0 0 0 0 0 0 0 0
C 0 0 0 0 0 0 0 0
D 0 0 0 0 0 0 0 0
E 1 0 1 0 1 0 1 0
F 1 0 1 0 1 0 1 0
G 0 0 0 0 0 0 0 0
H 0 0 0 0 0 0 0 0
I 0 0 0 0 0 0 0 0
J 1 0 1 0 1 0 1 0

Как удалить эти 100 имен переменных из вектора всех имен переменныхи использовать этот вектор для ссылки на имена столбцов матрицы?

Ответы [ 3 ]

0 голосов
/ 18 ноября 2018

Вот мой путь:

remove<-function(lets_to_be_removed,names){
    letters_with_names<-1:length(LETTERS) # each value corresponds to a letter
    names(letters_with_names)<-LETTERS # the letters, for example: letters_with_name["A"]==1 is TRUE
    result<-integer()
    for(letters in lets_to_be_removed){
        #check if it is only one letter
        res <- if(length(letters) == 1) letters_with_names[letters] else letters_with_names[letters[1]]:letters_with_names[letters[2]] 
        result<- c(result,res)
    }
    names(result)<-LETTERS[result]
    result #return the indices of the letters
}

И вы можете назвать его так:

letters <- list(c("B","D"),"F",c("G","I"))
letters
[[1]]
[1] "B" "D" # B:D sequence
[[2]]
[1] "F" # only one letter
[[3]]
[1] "G" "I" # G:I sequence

indices<-remove(letters,x)
indices # named vector
B C D F G H I 
2 3 4 6 7 8 9

x[ -indices ] # it is faster than [! x %in% indices] but if you want your method  then use [! x %in% names(indices)]
[1] "A" "E" "J"

В общем, лучше и быстрее использовать для индексов целые числа, чем символы.

0 голосов
/ 18 ноября 2018

Я заставил его работать, используя ответ hrbrmstr и длинный обходной путь. Если кто-нибудь может сказать мне, как сделать это менее грязно, пожалуйста, дайте мне знать.

# Copy prediction matrix and turn it into a dataframe for the "remove rows" function
varlist <- m
varlist <- as.data.frame(varlist)

# Create a column called "cat" with the rownames for the "remove rows" function
varlist$cat = rownames(varlist)
# Use the function to remove the rows from the copied df
varlist <- remove_rows(varlist, cat, ~B:C+F+G:I)
# Only keep the "cat" column and turn it into a vector
varlist <- varlist$cat
varlist <- varlist[['cat']]
# Copy prediction matrix and use "varlist" to put the correct rows to zero.
m_reduced <- m
m_reduced[ ,varlist] <- 0

Я был бы ДЕЙСТВИТЕЛЬНО счастлив, если бы кто-нибудь сказал мне, как убрать это чудовище.

0 голосов
/ 18 ноября 2018

Интригующий пример использования.Мы можем создать функцию, которая поможет вам сделать это так, как вы этого хотите.


ПРИМЕЧАНИЕ:

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

# get the terms of the formula
trms <- terms(remove_spec)

# get each element (will be each group separated by `+`
elements <- attr(trms, "term.labels")

# adding in assertions to validate `col` is in `xdf` and that only
# the restricted syntax is used in the formula and that it's valid 
# is up to the OP

# now, find the positions of all those strings
unlist(lapply(elements, function(y) {
  if (grepl(":", y)) {
    rng <- strsplit(y, ":")[[1]]
    which(x[,col] == rng[1]) : which(x[,col] == rng[2])
  } else {
    which(x[,col] == y)
  }
}), use.names = FALSE) -> to_exclude

, как я вроде закончил с этим q (а имена строк - 1980-е годы :-).Обратите внимание на предостережения в конце ответа.

Другие могут свободно использовать это в фактическом матричном ответе для варианта использования ОП.


Мы создадим некоторые смоделированные данные (таким образом, я могу увеличить пример, если вы хотите более крупный пример):

library(dplyr) # mostly for saner data frame constructor & printing

set.seed(2018-11-18)

data_frame(
  cat = LETTERS,
  val1 = sample(100, length(cat), replace = TRUE),
  val2 = sample(100, length(cat), replace = TRUE),
  val3 = sample(100, length(cat), replace = TRUE)
) -> xdf

xdf
## # A tibble: 26 x 4
##    cat    val1  val2  val3
##    <chr> <int> <int> <int>
##  1 A        87    98     5
##  2 B        30    69    39
##  3 C        87     1    32
##  4 D        65    46    87
##  5 E         4    69     6
##  6 F        53    20    31
##  7 G        43    51    84
##  8 H        27    43    65
##  9 I        27     9    10
## 10 J        10    94    11
## # ... with 16 more rows

(tibble печать - это def >> базовая печать IMO, но я отступаю).

Теперь вы хотите использовать строки для указания как отдельных элементов, так и диапазонов, и иметь что-то, что определяет, что делать под крышками.Для этого нам понадобятся функции и , в которых мы можем воспользоваться специальным классом R - forumla - чтобы помочь с более компактным синтаксисом.то есть было бы неплохо иметь возможность вызывать такую ​​функцию:

remove_rows(xdf, cat, ~B:C+F+G:I)

, которая будет искать диапазон "B": "C" в столбце catв xdf найдите положение «F», а затем диапазон «G»: «I» и верните фрейм данных с исключенными?Да, да, это будет.Итак, давайте построим это!

#' @param x data frame
#' @param col bare column name to use for the comparison
#' @param formula restricted operators are `:` for range and `+` for additing selectors
remove_rows <- function(x, col, remove_spec) {

  # this is pure convenience we could just as easily have forced folks 
  # to pass in a string (and we can modify it to handle both)
  col <- as.character(substitute(col)) 

  # get the terms of the formula
  trms <- terms(remove_spec)

  # get each element (will be each group separated by `+`
  elements <- attr(trms, "term.labels")

  # adding in assertions to validate `col` is in `xdf` and that only
  # the restricted syntax is used in the formula and that it's valid 
  # is up to the OP

  # now, find the positions of all those strings
  unlist(lapply(elements, function(y) {
    if (grepl(":", y)) {
      rng <- strsplit(y, ":")[[1]]
      which(x[,col] == rng[1]) : which(x[,col] == rng[2])
    } else {
      which(x[,col] == y)
    }
  }), use.names = FALSE) -> to_exclude

  # and get rid of those puppies
  x[-to_exclude,]

}

Теперь мы можем вызывать ее для действительных значений:

remove_rows(xdf, cat, ~B:C+F+G:I)
## # A tibble: 20 x 4
##    cat    val1  val2  val3
##    <chr> <int> <int> <int>
##  1 A        87    98     5
##  2 D        65    46    87
##  3 E         4    69     6
##  4 J        10    94    11
##  5 K        37    86    52
##  6 L        89    64    44
##  7 M        61    10    28
##  8 N        79    52    89
##  9 O        71    33    77
## 10 P        45    33    77
## 11 Q        56    97    29
## 12 R        10    28    39
## 13 S        25     7    71
## 14 T        86    57    51
## 15 U        92     2    15
## 16 V        25    36    12
## 17 W        90    78    10
## 18 X        20    82    90
## 19 Y        39    84    13
## 20 Z        43    93    18

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...