Обединяване на кадри с данни с предвидими правописни грешки

Трябва да обединя две рамки с данни. Първият изглежда така:

> df1 <- data.frame(Artist = c("Vincent van ", "Vincent van ", "Theo van Gogh", "Alexandre", "Alexandre"), Location = c("a","a","a","b","c"), time = c(1,2,1,1,1))
> df1
         Artist Location time
1  Vincent van         a    1
2  Vincent van         a    2
3 Theo van Gogh        a    1
4     Alexandre        b    1
5     Alexandre        c    1

И второто:

> df2 <- data.frame(Artist = c("Vincent van Gogh", "Theo van Gogh", "Alexandre Dumas", "Alexandre Dumas"), HomeNumber = c(123,234,456,789), Location = c( "a","a","b","c"))
> df2
            Artist HomeNumber Location
1 Vincent van Gogh        123        a
2    Theo van Gogh        234        a
3  Alexandre Dumas        456        b
4  Alexandre Dumas        789        c

И искам този кадър с данни:

> df3 <- data.frame(Artist = c("Vincent van ", "Vincent van ", "Theo van Gogh", "Alexandre", "Alexandre"), Location = c("a","a","a","b","c"), time = c(1,2,1,1,1), HomeNumber = c(123,123,234,456,789))
> df3
         Artist Location time HomeNumber
1  Vincent van         a    1        123
2  Vincent van         a    2        123
3 Theo van Gogh        a    1        234
4     Alexandre        b    1        456
5     Alexandre        c    1        789
> 

Обединяването ще работи само за Тео:

    > df3 <- merge(df1, df2, by.x = "Artist", by.y = "Artist", all.x =TRUE)
> df3
         Artist Location.x time HomeNumber Location.y
1     Alexandre          b    1         NA       <NA>
2     Alexandre          c    1         NA       <NA>
3 Theo van Gogh          a    1        234          a
4  Vincent van           a    1         NA       <NA>
5  Vincent van           a    2         NA       <NA> 

Причината е двойна: (а) Винсент липсва част от фамилията си в df1. (б) Александър е името на Александър Дюма-старши и Александър Дюма-младши.

Мога да се справя с (a) с df1$Artist <- gsub("Vincent van $","Vincent van Gogh", df1$Artist), но данните ми всъщност са много големи и преди да изпълня gsub, първо трябва да знам пълното име на Винсент. Едно възможно решение би било използването на grep("Vincent van "... в df2, изграждане на функция, която ако дължината на резултантния вектор е 1, бих използвал gsub, за да използвам върнатите df2$Artist до df1. Не знам как да го направя.

(b) е малко трудно за мен. Едно решение, за което се сещам (но не мога да кодирам), е първо да използвам ifфункция, за да избера Александър от едно местоположение, и след това да използвам решението за (a) до gsub името.

Мисля, че решаването на (a) и (b) ще върне желаното от мен df3. Имате ли идея как мога ефективно да обединя тези кадри с данни? Благодаря!

РЕДАКТИРАНЕ: Имайте предвид, че Alexandre всъщност са две различни единици. По този начин, когато се сливат, двете трябва да имат свързаните с тях HomeNumber и Location. Vincent е една единствена единица, но с две наблюдения във времето.


person Lucarno    schedule 23.04.2013    source източник
comment
Можете да опитате с функцията match(), където можете да поставите location като аргумент на съвпадението и останалите колони да се показват в нов data.frame   -  person Duck    schedule 23.04.2013
comment
функцията agrep прави размито съпоставяне на низове. Можете също така да предприемете няколко стъпки за прехвърляне като tolower и премахване на препинателни знаци, за да помогнете... Но най-краткият отговор е, че прехвърлянето на данни е досадно!   -  person Justin    schedule 23.04.2013
comment
@Duck: Може да помогне, но не виждам как ще реши проблема. Благодаря! @Джъстин: Знам! Изключително досаден. Вече използвах tolower, chartr и някои други функции.   -  person Lucarno    schedule 23.04.2013


Отговори (1)


Надявате се, че този резултат е саботиран от факта, че трябва да имате два реда във всяка рамка с данни, които искате да считате за имащи един и същ идентификатор, а именно Alexandre редовете. Процесът JOIN ще направи това съвпадение 2 x 2:

df2$short <- substr(df2$Artist, 1,7)
df1$short <- substr(df1$Artist, 1,7)
(dfmer <- merge(df1, df2, by="short") )
#-----
    short      Artist.x Location.x time         Artist.y HomeNumber Location.y
1 Alexand     Alexandre          b    1  Alexandre Dumas        456          b
2 Alexand     Alexandre          b    1  Alexandre Dumas        789          c
3 Alexand     Alexandre          c    1  Alexandre Dumas        456          b
4 Alexand     Alexandre          c    1  Alexandre Dumas        789          c
5 Theo va Theo van Gogh          a    1    Theo van Gogh        234          a
6 Vincent  Vincent van           a    1 Vincent van Gogh        123          a
7 Vincent  Vincent van           a    2 Vincent van Gogh        123          a

Можете да използвате !duplicated за местоположение и време, ако искате да изберете първите случаи:

> dfmer[!duplicated( dfmer[, c("Location.x", "time")]), ]
    short      Artist.x Location.x time         Artist.y HomeNumber Location.y
1 Alexand     Alexandre          b    1  Alexandre Dumas        456          b
3 Alexand     Alexandre          c    1  Alexandre Dumas        456          b
5 Theo va Theo van Gogh          a    1    Theo van Gogh        234          a
7 Vincent  Vincent van           a    2 Vincent van Gogh        123          a

В отговор на опасението (по-рано не е повдигнато, че местоположението трябва да се добави като свързваща променлива:

> (dfmer <- merge(df1, df2, by=c("short", "Location") ) )
    short Location      Artist.x time         Artist.y HomeNumber
1 Alexand        b     Alexandre    1  Alexandre Dumas        456
2 Alexand        c     Alexandre    1  Alexandre Dumas        789
3 Theo va        a Theo van Gogh    1    Theo van Gogh        234
4 Vincent        a  Vincent van     1 Vincent van Gogh        123
5 Vincent        a  Vincent van     2 Vincent van Gogh        123
person IRTFM    schedule 23.04.2013
comment
Благодаря, @Dwin. Обърнете внимание обаче, че Alexandre от Location 'c' има грешен HomeNumber - person Lucarno; 30.04.2013
comment
Ако HomeNumber е свързан със споделен идентификатор, както смятам, че е с Location, тогава трябва да добавите идентификатора към променливите by. - person IRTFM; 30.04.2013