Индексирование матрицы фрейма данных без приведения типов - PullRequest
0 голосов
/ 05 сентября 2018

Я пытаюсь заменить значения, соответствующие условию (меньше нуля) в одном data.frame, значениями из другого:

> df
  id val1 val2 val3
1  a    1    0   -1
2  b   -1   NA    2

> replacevals
  id val1 val2 val3
1  a    1    3    0
2  b    2   NA    3

Желаемый вывод:

  id val1 val2 val3
1  a    1    0    0
2  b    2   NA    2

Я знаю, что два кадра данных структурированы одинаково. Я могу сделать желаемую замену, как это ...

negs <- !is.na( df ) & df < 0  # logical matrix
df[negs] <- replacevals[negs]

... но теперь классы столбцов изменились:

> sapply(df, class)
         id        val1        val2        val3 
"character" "character"   "numeric" "character" 

В этом случае их можно преобразовать обратно в правильные значения путем сопоставления классов из данных замещения с окончательными данными:

df[] <- Map(`class<-`, df, sapply(replacevals, class))

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

Матричное индексирование (x [i] с использованием логической или двухзначной целочисленной матрицы i) с использованием [не рекомендуется. Для извлечения x сначала приводится к матрице. Для замены индексы логической матрицы должны быть того же размера, что и x. Замены выполняются по одному столбцу за раз с возможными принуждениями нескольких типов.

Есть ли лучший способ сделать это?

Данные

df <- data.frame(id = c('a','b'), val1 = c(1,-1), val2 = c(0,NA),
                 val3 = c(-1,2), stringsAsFactors = F)
replacevals <- data.frame(id = c('a','b'), val1 = c(1,2), val2 = c(3,NA), 
                          val3 = c(0,3), stringsAsFactors = F)

1 Ответ

0 голосов
/ 05 сентября 2018

Нам нужно создать условие только для числовых столбцов

j1 <- sapply(df, is.numeric)
negs <- !is.na( df[j1] ) & df[j1] < 0  # logical matrix
df[j1][negs] <- replacevals[j1][negs]

df
#  id val1 val2 val3
#1  a    1    0    0
#2  b    2   NA    2

str(df)
#'data.frame':  2 obs. of  4 variables:
# $ id  : chr  "a" "b"
# $ val1: num  1 2
# $ val2: num  0 NA
# $ val3: num  0 2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...