R: сопоставление строк по двум столбцам - PullRequest
0 голосов
/ 23 марта 2019

В настоящее время я пытаюсь найти векторизованный способ сопоставления по двум значениям в одной строке.У меня есть следующие два упрощенных фрейма данных:

# Dataframe 1: Displaying all my observations
df1 <- data.frame(c(1, 2, 3, 4, 5, 6, 7, 8),
                  c("A", "B", "C", "D", "A", "B", "A", "C"), 
                  c("B", "E", "D", "A", "C", "A", "D", "A"))
colnames(df1) <- c("ID", "Number1", "Number2")

> df1
  ID Number1 Number2
1  1       A       B
2  2       B       E
3  3       C       D
4  4       D       A
5  5       A       C
6  6       B       A
7  7       A       D
8  8       C       A

# Dataframe 2: Matrix of observations I am interested in
df2 <- matrix(c("A", "B",
                "D", "A",
                "C", "B",
                "E", "D"),
              ncol = 2,
              byrow = TRUE)

> df2
     [,1] [,2]
[1,] "A"  "B" 
[2,] "D"  "A" 
[3,] "C"  "B" 
[4,] "E"  "D" 

Я пытаюсь создать новый столбец в df1, в котором указано TRUE, только если в df2 присутствует точная комбинация (например, ID = 1эквивалентно первой строке в df2, потому что они оба состоят из A и B).Кроме того, если есть ярлык, я также хотел бы, чтобы статус был ИСТИНА, если числа поменялись местами, то есть df1 $ Number1 соответствует df2 [i, 2] и df1 $ Number2 соответствует df2 [i, 1] (например, для ID= 7, комбинация в df1 это A, D и в df2, комбинация D, A -> TRUE).

Мой желаемый результат выглядит так:

> df1
  ID Number1 Number2 Status
1  1       A       B   TRUE
2  2       B       E  FALSE
3  3       C       D  FALSE
4  4       D       A   TRUE
5  5       A       C  FALSE
6  6       B       A  TRUE
7  7       A       D  TRUE
8  8       C       A  FALSE

ВсеЯ дошел до того, что это:

for (i in 1:nrow(df1)) {
  for (j in 1:nrow(df2)) {
    Status <- ifelse(df1$Number1[i] %in% df2[j,1] && 
                     df1$Number2[i] %in% df2[j,2], TRUE, FALSE)
    StatusComb[i,j] <- Status
  }
  df1$Status[i] <- ifelse(any(StatusComb[i,]) == TRUE, TRUE, FALSE)
}

Это действительно неэффективно (вы можете ясно сказать, что я новичок в R) и тоже не очень хорошо выглядит.Буду признателен за любую помощь!

Ответы [ 2 ]

0 голосов
/ 23 марта 2019

Вы можете определить переменную combination, которую вы хотите искать в алфавитном порядке, как показано ниже:

combination <- apply(df2, 1, function(x) {
  paste(sort(x), collapse = '')
})
combination
[1] "AB" "AD" "BC" "DE"

А затем изменить поле состояния на основе объединения поля Number

library(dplyr)
df1 %>%
  rowwise() %>%
  mutate(S = paste(sort(c(Number1, Number2)), collapse = "")) %>%
  mutate(Status = ifelse(S %in% combination, TRUE, FALSE))
Source: local data frame [8 x 5]
Groups: <by row>

# A tibble: 8 x 5
     ID Number1 Number2 S     Status
  <dbl> <chr>   <chr>   <chr> <lgl> 
1     1 A       B       AB    TRUE  
2     2 B       E       BE    FALSE 
3     3 C       D       CD    FALSE 
4     4 D       A       AD    TRUE  
5     5 A       C       AC    FALSE 
6     6 B       A       AB    TRUE  
7     7 A       D       AD    TRUE  
8     8 C       A       AC    FALSE 

Данные:

Я установил stringsAsFactors = F в кадре данных

df1 <- data.frame(c(1, 2, 3, 4, 5, 6, 7, 8),
                    c("A", "B", "C", "D", "A", "B", "A", "C"), 
                    c("B", "E", "D", "A", "C", "A", "D", "A"), stringsAsFactors = F)
colnames(df1) <- c("ID", "Number1", "Number2")
0 голосов
/ 23 марта 2019

Один из методов будет merge вещи вместе.

Адаптируя ваши данные, чтобы учесть обратные метки, я переверну df2 на себя и наброшу:

df2 <- rbind.data.frame(df2, df2[,c(2,1)])
colnames(df2) <- c("Number1", "Number2")
df2$a <- TRUE
df2
#   Number1 Number2    a
# 1       A       B TRUE
# 2       D       A TRUE
# 3       C       B TRUE
# 4       E       D TRUE
# 5       B       A TRUE
# 6       A       D TRUE
# 7       B       C TRUE
# 8       D       E TRUE

Я добавил a, чтобы он был объединен. Оттуда:

df3 <- merge(df1, df2, all.x = TRUE)
df3$a <- !is.na(df3$a)
df3[ order(df3$ID), ]
#   Number1 Number2 ID     a
# 1       A       B  1  TRUE
# 5       B       E  2 FALSE
# 7       C       D  3 FALSE
# 8       D       A  4  TRUE
# 2       A       C  5 FALSE
# 4       B       A  6  TRUE
# 3       A       D  7  TRUE
# 6       C       A  8 FALSE

Если вы посмотрите на это раньше !is.na(df3$a), вы увидите, что столбец полностью TRUE и NA (NA не присутствовал в df2); если вам этого достаточно, то вы можете опустить средний шаг. Шаг order только потому, что порядок строк с merge не гарантирован (на самом деле я всегда нахожу это неудобно другим). Поскольку ранее он был заказан ID, я вернулся к этому, но здесь эстетика полностью соответствовала желаемому результату.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...