Dúvida na comparação entre dois dataframes

Boa tarde pessoal,

Tenho dois dataframes, um chamado dado e outro chamado gff, cada um deles tem as colunas nome, localização, posição final e posição inicial. Entretanto os nomes entre eles não são correspondentes. O que eu queria fazer é comparar o valores de loc, inicio e fim de cada coluna no dataframe dado e ver se a localização é exatamente igual ao dataframe gff e se os valores para inicio e fim estão dentro do que está no dataframe gff (não precisa ser igual, precisa estar entre os valores). Caso esteja presente entre os valores, criar uma nova coluna no arquivo gff e nessa coluna conter o nome da linha do dataframe dado que cumpriu os requisitos.

Segue um exemplo reprodutível.

library(tidyverse)
#> Warning: package 'ggplot2' was built under R version 4.1.3
#> Warning: package 'tibble' was built under R version 4.1.3
#> Warning: package 'dplyr' was built under R version 4.1.3
dado <- tibble(nome = c("seq_1", "seq_2", "seq_3"),
              loc = c("c1", "c2", "c3"),
              inicio = c(3, 50, 100),
              fim = c(20, 89, 250))

dado
#> # A tibble: 3 x 4
#>   nome  loc   inicio   fim
#>   <chr> <chr>  <dbl> <dbl>
#> 1 seq_1 c1         3    20
#> 2 seq_2 c2        50    89
#> 3 seq_3 c3       100   250
gff <- tibble(nome = c("gene1", "gene2", "gene3"),
                  loc = c("c1", "c2", "c3"),
                  inicio = c(1, 60, 253),
                  fim = c(25, 95, 300))

gff
#> # A tibble: 3 x 4
#>   nome  loc   inicio   fim
#>   <chr> <chr>  <dbl> <dbl>
#> 1 gene1 c1         1    25
#> 2 gene2 c2        60    95
#> 3 gene3 c3       253   300

Created on 2022-06-28 by the reprex package (v2.0.1)

Nesse caso o resultado esperado seria que as duas primeiras linhas cumpram os requisitos e que uma nova coluna fosse criada com os nomes “seq_1” e “seq_2” e na terceira linha um NA… Existe também a possibilidade de mais de uma seq cumprir os requisitos… Como eu poderia resolver essa questão?

Obrigada desde já.

Laila,

Não sei ao certo se entendi a pergunta. Minha principal dúvida é em relação a inicio e fim só precisarem estar “entre os valores”. No seu exemplo, você diz que a segunda linha de gff deve corresponder com "seq_2", mas o valor de inicio na segunda linha de dado (50) não está entre os valores da segunda linha de gff (60 e 95).

De qualquer modo, tentei fazer um algoritmo que atendesse ao que eu entendi dos seus requisitos. Minha solução sua um loop simples ao longo das linhas de gff.

library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union

# Exemplo de dado
dado <- tibble::tibble(
  nome = c("seq_1", "seq_2", "seq_3"),
  loc = c("c1", "c2", "c3"),
  inicio = c(3, 50, 100),
  fim = c(20, 89, 250)
)

# Exemplo de gff
gff <- tibble::tibble(
  nome = c("gene1", "gene2", "gene3"),
  loc = c("c1", "c2", "c3"),
  inicio = c(1, 60, 253),
  fim = c(25, 95, 300)
)

# Para cada linha de gff...
for (i in seq_len(nrow(gff))) {

  # Filtrar de dado as linhas com:
  # 1. `dado$loc` == `gff$loc`
  # 2. `gff$inicio` <= `dado$inicio` <= `gff$fim`
  # 3. `gff$inicio` <= `dado$fim` <= `gff$fim`
  corresp <- dado |>
    filter(loc == gff[[i, "loc"]]) |>
    filter(between(inicio, gff[[i, "inicio"]], gff[[i, "fim"]])) |>
    filter(between(fim, gff[[i, "inicio"]], gff[[i, "fim"]])) |>
    pull(nome)  

  # Se for encontrada correspondência, adicionar em gff
  if (length(corresp) > 0) {
    gff[[i, "corresp"]] <- corresp
  }
}

# Resultado
gff
#> # A tibble: 3 × 5
#>   nome  loc   inicio   fim corresp
#>   <chr> <chr>  <dbl> <dbl> <chr>  
#> 1 gene1 c1         1    25 seq_1  
#> 2 gene2 c2        60    95 <NA>   
#> 3 gene3 c3       253   300 <NA>

Created on 2022-06-28 by the reprex package (v2.0.1)

Oi Caio, é desse jeito mesmo que você entendeu, houve um erro de digitação na hora de colocar o valor. Entretanto, com os meus dados reais não funcionou. Não sei se pode ser por causa do tamanho de linhas serem diferentes. No dataframe dado eu tenho 106996 linhas e no dataframe gff eu tenho 17650. Aparece o seguinte erro:

Error:
! Assigned data corresp must be compatible with row subscript i.
x 1 row must be assigned.
x Assigned data has 8 rows.
i Row updates require a list value. Do you need list() or as.list()?

Acho que o problema é que pode haver mais de uma correspondência. Nesse caso, corresp precisaria ser uma list-column.

Tente trocar a linha

    gff[[i, "corresp"]] <- corresp

por

    gff[[i, "corresp"]] <- list(corresp)

Funcionou Caio! Muitíssio obrigada :smiley:

1 curtida