Условно разделить уровень факторов на два разных уровня - PullRequest
0 голосов
/ 05 июня 2018

У меня есть фрейм данных, например:

df <- data.frame(
        type = c("BND", "INV", "BND", "DEL", "TRA"),
        chrom1 = c(1, 1, 1, 1, 1),
        chrom2 = c(1, 1, 2, 1, 3)
        )

Я хочу переназначить все df[df$type=='BND',] экземпляры на INV или TRA в зависимости от значений в chrom1 и chrom2,

Я пытаюсь использовать fct_recode из пакета forcats следующим образом:

library(forcats)

df$type <- ifelse(df$type=="BND", 
                  ifelse(df$chrom1 == df$chrom2,
                         fct_recode(df$type, BND="INV"),
                         fct_recode(df$type, BND="TRA")),
                  df$type)

Однако это перекодирует мои коэффициенты в числа:

  type chrom1 chrom2
1    1      1      1
2    3      1      1
3    1      1      2
4    2      1      1
5    4      1      3

Вот мой ожидаемый результат:

  type chrom1 chrom2
1    INV      1      1 # BND -> INV as chrom1==chrom2
2    INV      1      1
3    TRA      1      2 # BND -> TRA as chrom1!=chrom2
4    DEL      1      1
5    TRA      1      3

Как я могу таким образом разделить фактор на два уровня?

Ответы [ 4 ]

0 голосов
/ 05 июня 2018

Для полноты, вот также краткое data.table решение:

library(data.table)
setDT(df)[type == "BND" & chrom1 == chrom2, type := "INV"][type == "BND", type := "TRA"][]
   type chrom1 chrom2
1:  INV      1      1
2:  INV      1      1
3:  TRA      1      2
4:  DEL      1      1
5:  TRA      1      3

Преимущество заключается в том, что type обновляется ссылка , например, без копирования всего объекта и только для тех строк, для которых применяется условие.

0 голосов
/ 05 июня 2018

Вы также можете сделать это с case_when()

library(tidyverse)

df %>% 
  mutate(type = as.factor(case_when(
    type == 'BND' & chrom1 == chrom2 ~ 'INV', 
    type == 'BND' & chrom1 != chrom2 ~ 'TRA',
    TRUE  ~ as.character(type))))

data:

df <- data.frame(
  type = c("BND", "INV", "BND", "DEL", "TRA"),
  chrom1 = c(1, 1, 1, 1, 1),
  chrom2 = c(1, 1, 2, 1, 3)
)
0 голосов
/ 05 июня 2018

Или просто

df$type[df$type == "BND"] <- with(df, 
                                  ifelse(df[type == "BND", ]$chrom1 == 
                                           df[type == "BND", ]$chrom2,
                                         "INV", "TRA"))
> df
  type chrom1 chrom2
1  INV      1      1
2  INV      1      1
3  TRA      1      2
4  DEL      1      1
5  TRA      1      3
0 голосов
/ 05 июня 2018

Мой способ мышления таков: (1) Индексируйте строки, которые вы хотите изменить, (2) вы делаете оператор ifelse.Я надеюсь, что это поможет:

  df <- data.frame(
  type = c("BND", "INV", "BND", "DEL", "TRA"),
  chrom1 = c(1, 1, 1, 1, 1),
  chrom2 = c(1, 1, 2, 1, 3)
)

indexBND<-which(df$type=="BND")
df$type[indexBND]<-ifelse(df$chrom1[indexBND] == df$chrom2[indexBND], df$type[indexBND] <- "INV", "TRA")

df
#   type chrom1 chrom2
# 1  INV      1      1
# 2  INV      1      1
# 3  TRA      1      2
# 4  DEL      1      1
# 5  TRA      1      3

Ура!

...