Удалить строки, содержащие разные буквы или пропущенные данные для двух столбцов - PullRequest
1 голос
/ 12 февраля 2020

Я анализирую большой набор данных в R studio, и я не очень опытен в программировании. Я хотел бы удалить строки, которые содержат разные буквы для столбцов CONSENSUSMAP и SVEVOMAP. Также, если отсутствуют данные для столбца «CONSENSUSMAP».

Я напишу эту таблицу в качестве примера:

CLONEID | CONSENSUSMAP| SVEVOMAP
1228104 |      NA     |    chr1A
2277691 |      NA     |    chr1A
2277607 |      1A     |    chr1A
1E+08   |      NA     |    chr1A
1229677 |      1B     |    chr1A
1126457 |      7B     |    chr7B

Я хотел бы получить следующий вывод:

CLONEID | CONSENSUSMAP| SVEVOMAP
2277607 |       1A    |    chr1A
1126457 |       7B    |    chr7B

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

Ответы [ 3 ]

3 голосов
/ 12 февраля 2020

Следующее решение dplyr сделает то, о чем просит вопрос.

library(dplyr)

df1 %>%
  filter(!is.na(CONSENSUSMAP)) %>%
  mutate(newcol = sub("^[^[:digit:]]*(\\d+.*$)", "\\1", SVEVOMAP)) %>%
  filter(CONSENSUSMAP == newcol) %>%
  select(-newcol)
#  CLONEID CONSENSUSMAP SVEVOMAP
#1 2277607           1A    chr1A
#2 1126457           7B    chr7B

Правка.

Вот два других способа, оба с dplyr второй использует пакет stringr.

df1 %>%
  filter(!is.na(CONSENSUSMAP)) %>%
  rowwise() %>%
  filter(grepl(CONSENSUSMAP, SVEVOMAP))
#Source: local data frame [2 x 3]
#Groups: <by row>
#
## A tibble: 2 x 3
#  CLONEID CONSENSUSMAP SVEVOMAP
#  <chr>   <chr>        <chr>   
#1 2277607 1A           chr1A   
#2 1126457 7B           chr7B   


df1 %>%
  filter(!is.na(CONSENSUSMAP)) %>%
  filter(stringr::str_detect(SVEVOMAP, CONSENSUSMAP))
#  CLONEID CONSENSUSMAP SVEVOMAP
#1 2277607           1A    chr1A
#2 1126457           7B    chr7B

Data.

df1 <-
structure(list(CLONEID = c("1228104", "2277691", "2277607", "1e+08", 
"1229677", "1126457"), CONSENSUSMAP = c(NA, NA, "1A", NA, "1B", 
"7B"), SVEVOMAP = c("chr1A", "chr1A", "chr1A", "chr1A", "chr1A", 
"chr7B")), row.names = c(NA, -6L), class = "data.frame")
2 голосов
/ 12 февраля 2020

Возможный base способ:

idx <- with(df, !is.na(CONSENSUSMAP) & mapply(grepl, CONSENSUSMAP, SVEVOMAP))

df[idx, ]

Вывод:

  CLONEID CONSENSUSMAP SVEVOMAP
3 2277607           1A    chr1A
6 1126457           7B    chr7B

Обратите внимание, что это выглядит только в том случае, если весь шаблон в CONSENSUSMAP соответствует чему-либо в SVEVOMAP.

Если в конце вы действительно используете только буквы, давайте немного изменим пример:

  CLONEID CONSENSUSMAP SVEVOMAP
1 1228104         <NA>    chr1A
2 2277691         <NA>    chr1A
3 2277607           1A    chr1A
4   1e+08         <NA>    chr1A
5 1229677           1B    chr1A
6 1126457           7B    chr6B

Здесь последняя запись не будет извлечена предыдущим методом, но будет со следующим:

idx <- with(df, !is.na(CONSENSUSMAP) & sub('\\d+', '', CONSENSUSMAP) == sub('chr\\d+(.*$)', '\\1', SVEVOMAP))

df[idx, ]

  CLONEID CONSENSUSMAP SVEVOMAP
3 2277607           1A    chr1A
6 1126457           7B    chr6B
2 голосов
/ 12 февраля 2020

Мы можем обернуть с na.omit, а затем distinct

library(dplyr)
df1 %>%
        filter(!is.na(CONSENSUSMAP)) %>%
        distinct(SVEVOMAP, .keep_all = TRUE)
#  CLONEID CONSENSUSMAP SVEVOMAP
#1 2277607           1A    chr1A
#2 1126457           7B    chr7B

Или, если он основан на подстроке, тогда

library(stringr)
df1 %>%
   filter(!is.na(CONSENSUSMAP), CONSENSUSMAP == str_sub(SVEVOMAP, 4, 5))
#   CLONEID CONSENSUSMAP SVEVOMAP
#1 2277607           1A    chr1A
#2 1126457           7B    chr7B

Или с str_remove

df1 %>%
   filter(!is.na(CONSENSUSMAP), CONSENSUSMAP == str_remove(SVEVOMAP, 'chr'))

данные

df1 <- structure(list(CLONEID = c("1228104", "2277691", "2277607", "1e+08", 
"1229677", "1126457"), CONSENSUSMAP = c(NA, NA, "1A", NA, "1B", 
"7B"), SVEVOMAP = c("chr1A", "chr1A", "chr1A", "chr1A", "chr1A", 
"chr7B")), row.names = c(NA, -6L), class = "data.frame")
...