Манипулировать R Dataframe условно - PullRequest
0 голосов
/ 06 мая 2018

У меня есть фрейм данных с целыми числами, и я хотел бы преобразовать их в двоичную систему (или третичную, если хотите), где они становятся равными 1, если больше x, -1, если меньше y, и 0 еще.

Это пример кадра данных:

  var1 var2 var3
  30    13   2
  20    29   3

Вот как должен выглядеть мой новый фрейм данных (х равен 27, а у 4):

  var1 var2 var3
  1     0   - 1
  0     1    -1

Есть ли простой способ сделать это?

Ответы [ 2 ]

0 голосов
/ 06 мая 2018

Вот довольно быстрый базовый ответ. Это будет очень быстро, если набор данных довольно мал по сравнению с объемом доступной оперативной памяти.

dat[] <- findInterval(as.matrix(dat), vec = c(4, 27),
                      rightmost.closed=TRUE) - 1L

Здесь, поскольку каждый столбец имеет одинаковые разрывы, вы конвертируете копию data.frame в матрицу и запускаете findInterval, используя эти разрывы. Rightmost.closed = TRUE гарантирует, что эти значения включены в их набор. Затем, поскольку findInterval возвращает значения, начинающиеся с 0, вычтите 1, чтобы получить нужные значения.

Использование dat[] <- помещает полученный вектор в data.frame.

Это возвращает

dat
  var1 var2 var3
1    1    0   -1
2    0    1   -1

данные

dat <- 
structure(list(var1 = c(30L, 20L), var2 = c(13L, 29L), var3 = 2:3),
.Names = c("var1", "var2", "var3"), class = "data.frame",
row.names = c(NA, -2L))
0 голосов
/ 06 мая 2018

Вот довольно лаконичный способ справиться с этим с помощью mutate_all и case_when из dplyr:

x <- 27
y <- 4
df %>% mutate_all(funs(case_when(. > x ~ 1, . < y ~ -1, TRUE ~ 0)))

#   var1 var2 var3
# 1    1    0   -1
# 2    0    1   -1

Это также можно сделать с помощью вложенного приложения ifelse, хотя оно менее расширяемо (т. Е. Довольно быстро становится громоздким, если ваш список условий увеличивается):

ifelse(df > x, 1, ifelse(df < y, -1, 0))

Хотя, так как вы упоминаете, что делаете «третичное» кодирование, возможно, это все, что вам нужно.

...