2015-09-11 2 views
1

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

df1 <- data.frame(A=c(.87,.11,.44,.45), B=c("I have a beard", "I slept for two hours", "I have had two courses","this is not true")) 

df2 <- data.frame(X=c(127,10,433,344,890,4),Y=c("have","beard","syllabus","true","three","maths")) 

Я хочу сделать pmatch и я ожидаю выход следующего

A  B       X  Y 
.87 I have a beard    127  have 
.11 I slept for two hours  NA  NA 
.44 I have had two courses  127  have 
.45 this is not true    344  true 

Я хотел бы частичное совпадение с левым присоединиться на df1. Я хочу получить максимум из двух матчей (например, в «У меня есть борода», строка «имеет» имеет 127, а «борода» - 10, и я хочу получить более высокий результат. Любые предложения?

ответ

1

Это dplyr метод не нужен join (что разумно, так как у вас нет общего столбца для соединения). Он объединяет 2 набора данных и находит совпадения. Пока у вас нет тысяч строк, он будет работать достаточно быстро. Конечно, вы можете сделать сценарий меньше, но вы можете запустить этот шаг за шагом, чтобы увидеть, как это работает.

df1<- data.frame(A=c(.87,.11,.44,.45), B=c("I have a beard", "I slept for two hours", "I have had two courses","this is not true")) 

df2<- data.frame(X=c(127,10,433,344,890,4),Y=c("have","beard","syllabus","true","three","maths")) 

library(dplyr) 

df1 %>% 
    rowwise() %>% 
    do(data.frame(.,df2)) %>%     # combine datasets 
    do(data.frame(.,flag = grepl(.$Y,.$B))) %>% # for each row check if there's a match and name it flag 
    ungroup %>% 
    group_by(A,B) %>%       # for each A and B 
    mutate(N=sum(flag)) %>%      # count how many matches you have 
    filter(flag==TRUE | N == 0) %>%    # keep only A,B where you have some matches or no match at all 
    top_n(1,X) %>%        # pick one row based on max value of X 
    ungroup %>% 
    mutate(Y = ifelse(flag==FALSE,NA,as.character(Y)), # if there's no match replace Y with NA 
     X = ifelse(flag==FALSE,NA,X)) %>%    # if there's no match replace X with NA 
    select(-c(flag,N)) 


#  A      B X Y 
# 1 0.87   I have a beard 127 have 
# 2 0.11 I slept for two hours NA NA 
# 3 0.44 I have had two courses 127 have 
# 4 0.45  this is not true 344 true 

поэкспериментируйте и изменять различные значения столбцов, чтобы увидеть, как это работает. вы можете быть в состоянии обнаружить любые ошибки заранее.

+0

Awesome! Он работал как прелесть, хотя это заняло некоторое время :) – user3570187

+0

@ user3570187 Не должно быть значения для строки 2 (890 - это 'Y == three', что не так) –

+1

Да, вы правы. Я забыл также заменить значения X на NA. Исправит это как можно скорее. – AntoniosK

1

Другой вариант:

library(dplyr) 

df1 %>% 
    mutate(X = sapply(strsplit(as.character(B), ' '), 
        function(x) with(df2, max(X[Y %in% x])))) %>% 
    left_join(., df2) 

Что дает:

#Joining by: "X" 
#  A      B X Y 
#1 0.87   I have a beard 127 have 
#2 0.11 I slept for two hours -Inf <NA> 
#3 0.44 I have had two courses 127 have 
#4 0.45  this is not true 344 true 
Смежные вопросы