Перекрестное сравнение R-фреймов - PullRequest
0 голосов
/ 30 апреля 2018

У меня есть два фрейма данных R, у каждого есть группа (одна из 25 строк) и столбец позиции (целое число). Я хотел бы проверить для каждой записи кадра данных A, существует ли запись в кадре данных B, которая является частью той же группы, и дельта между ее целым числом позиции меньше 500. Если, поэтому я хочу отметить эту запись в фрейм данных A.

Так, например, первая запись в A будет соответствовать третьей записи в B (группа такая же, и разница между их позициями меньше 500 б.п.). Поэтому он был отмечен в выходной таблице.

head(A)
  group     pos
1  chr1 3202965
2  chr1 3000168
3  chr1 3000204
4  chr2 3000560
5  chr2 3000674
6  chr3 3000698

head(B)    
  group     pos
1  chr1 3180137
2  chr1 3200918
3  chr1 3202983
4  chr1 3309167
5  chr4 3458278
6  chr1 4249136

A_out <- magic(A,B)

head(A_out)
  group     pos out
1  chr1 3202965   +
2  chr1 3000168   -
3  chr1 3000204   -
4  chr2 3000560   -
5  chr2 3000674   -
6  chr3 3000698   -

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

Есть ли более разумный подход к этому?

Ответы [ 3 ]

0 голосов
/ 30 апреля 2018

sqldf очень удобно в таких случаях. Одна реализация может быть как:

library(sqldf)

df_result <- sqldf("select A.*, B.pos as posB from A left outer join B
      on A.group1 = B.group1 AND
      abs(A.pos - B.pos) <= 500")

#The result is available. Any transformation can be performed on the result as
df_result$out <- ifelse(is.na(df_result$posB), "-" , 
             ifelse(df_result$posB > df_result$pos,"+", "-"))
df_result
#   group1     pos    posB out
# 1   chr1 3202965 3202983   +
# 2   chr1 3000168      NA   -
# 3   chr1 3000204      NA   -
# 4   chr2 3000560      NA   -
# 5   chr2 3000674      NA   -
# 6   chr3 3000698      NA   -

Данные: Обратите внимание, что я изменил столбец group на group1, чтобы сделать его совместимым с sqldf.

A <- read.table(text = 
"group1     pos
1  chr1 3202965
2  chr1 3000168
3  chr1 3000204
4  chr2 3000560
5  chr2 3000674
6  chr3 3000698",
header = TRUE, stringsAsFactors = FALSE)

B <- read.table(text = 
"group1     pos
1  chr1 3180137
2  chr1 3200918
3  chr1 3202983
4  chr1 3309167
5  chr4 3458278
6  chr1 4249136",
header = TRUE, stringsAsFactors = FALSE)
0 голосов
/ 30 апреля 2018

Преобразование и условие ifelse для подмножества фрейма данных, основанного на значениях другого, должны помочь.

df1 <- read.table(text = "
      group     pos
    1  chr1 3202965
    2  chr1 3000168
    3  chr1 3000204
    4  chr2 3000560
    5  chr2 3000674
    6  chr3 3000698
    ",header = T)

df2 <- read.table(text = "
  group     pos
1  chr1 3180137
2  chr1 3200918
3  chr1 3202983
4  chr1 3309167
5  chr4 3458278
6  chr1 4249136
",header = T)

Преобразование будет проходить через каждый ряд df1. Условие ifelse создает новый столбец, значение которого основано на условии ifelse, как требуется. Необходимо выполнить условия df1 $ group% в группе% df2 $ и (df1 $ pos -df2 $ pos)> 500), чтобы установить для столбца out значение «+».

transform(df1,out = ifelse((df1$group %in% df2$group) & ((df1$pos -df2$pos) > 500), "+","-"))

  group     pos out
1  chr1 3202965   +
2  chr1 3000168   -
3  chr1 3000204   -
4  chr2 3000560   -
5  chr2 3000674   -
6  chr3 3000698   -
0 голосов
/ 30 апреля 2018

Вот одно решение с использованием пакета dplyr:

df1 <- read.table(text = "  group     pos
1  chr1 3202965
2  chr1 3000168
3  chr1 3000204
4  chr2 3000560
5  chr2 3000674
6  chr3 3000698", header = TRUE)

df2 <- read.table(text = "  group     pos
1  chr1 3180137
2  chr1 3200918
3  chr1 3202983
4  chr1 3309167
5  chr4 3458278
6  chr1 4249136", header = TRUE)

df3 <- left_join(df1, df2, by = 'group')

df3 <- df3 %>%
  mutate(out = ifelse(abs(pos.x - pos.y) <= 500 & !is.na(pos.y), '+', '-')) %>%
  select(group, pos = pos.x, out) %>%
  arrange(group, pos, desc(out)) %>%
  group_by(group, pos) %>%
  slice(1)

# A tibble: 6 x 3
# Groups: group, pos [6]
  group     pos out  
  <chr>   <int> <chr>
1 chr1  3000168 -    
2 chr1  3000204 -    
3 chr1  3202965 +    
4 chr2  3000560 -    
5 chr2  3000674 -    
6 chr3  3000698 -    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...