2015-09-28 4 views
1

Рассмотрим следующий кадр данных:найти один-к-одному, один-ко-многим и многие-к-одному отношения между столбцами

first_name last_name 
1   Al  Smith 
2   Al  Jones 
3  Jeff Thompson 
4  Scott Thompson 
5  Terry Dactil 
6  Pete  Zah 

data <- data.frame(first_name=c("Al","Al","Jeff","Scott","Terry","Pete"), 
        last_name=c("Smith","Jones","Thompson","Thompson","Dactil","Zah")) 

В этом кадре данных, есть три способа, которыми first_name является связанный с last_name:

  • Один на один (т.е. существует однозначная связь между first_name и last_name)
  • один ко много (т.е. точка один first_name несколько last_name значений)
  • Многие к одному (т.е. несколько значений first_name указывают на один last_name)

Я хочу, чтобы иметь возможность быстро идентифицировать каждый из этих трех случаев и выводить их в кадр данных. Таким образом, полученные кадры данных будут:

Один на один

first_name last_name 
1  Terry Dactil 
2  Pete  Zah 

Один ко многим

first_name last_name 
1   Al  Smith 
2   Al  Jones 

Многие на один

first_name last_name 
1  Jeff Thompson 
2  Scott Thompson 

Я хотел бы сделать это в течение пакет dplyr.

+2

Вы хотите, чтобы функция 'duplicated()' –

+0

[здесь] (http://www.cookbook-r.com/Manipulating_data/Finding_and_removing_duplicate_records/) представляет собой пример кода с использованием 'duplicated()', но я думаю, что это быть крутым, если бы вы могли дать нам что-то конкретное здесь, @RichardScriven. Я не пытаюсь решить эту проблему. ти. –

ответ

6

В общем, вы можете проверить, дублируется ли значение с помощью функции duplicated (как указано в комментарии по вашему вопросу) @RichardScriven. Однако, по умолчанию эта функция не помечает первый экземпляр элемента, который появляется несколько раз продублированы:

duplicated(c(1, 1, 1, 2)) 
# [1] FALSE TRUE TRUE FALSE 

Поскольку вы также хотите, чтобы забрать эти случаи, как правило, вы хотели бы работать duplicated на каждом векторе дважды, один раз вперед и назад один раз:

duplicated(c(1, 1, 1, 2)) | duplicated(c(1, 1, 1, 2), fromLast=TRUE) 
# [1] TRUE TRUE TRUE FALSE 

Я считаю, что это будет много печатать, так что я буду определять вспомогательную функцию, которая проверяет, является ли элемент появляется более одного раза:

d <- function(x) duplicated(x) | duplicated(x, fromLast=TRUE) 

Теперь логика вы хотите все простые однострочечники:

# One to one 
data[!d(data$first_name) & !d(data$last_name),] 
# first_name last_name 
# 5  Terry Dactil 
# 6  Pete  Zah 

# One to many 
data[d(data$first_name) & !d(data$last_name),] 
# first_name last_name 
# 1   Al  Smith 
# 2   Al  Jones 

# Many to one 
data[!d(data$first_name) & d(data$last_name),] 
# first_name last_name 
# 3  Jeff Thompson 
# 4  Scott Thompson 

Обратите внимание, что вы можете также определить d без помощи duplicated с помощью table функции:

d <- function(x) table(x)[x] > 1 

Хотя это альтернативное определение немного более кратким, я также считаю его менее читаемым.

+4

Я вроде бы хотел, чтобы меня зовут Терри Дактиль сейчас –

+0

@RichardScriven Я бы ожидал «Терри Дактиль», но да, это был бы отличный стартер разговора! – josliber

+0

: r не будет рассматривать функцию (x) duplicated (x) 'и' duplicated (x, fromLast = TRUE) 'как две отдельные части? –

Смежные вопросы