2013-05-29 10 views
6

Mam dwóch ramek danych:Liczba meczów pomiędzy dwoma strunami

df.1 <- data.frame(loc = c('A','B','C','C'), person = c(1,2,3,4), str = c("door/window/table", "window/table/toilet/vase ", "TV/remote/phone/window", "book/vase/car/chair")) 

Zatem

loc person        str 
1 A  1   door/window/table 
2 B  2 window/table/toilet/vase 
3 C  3 TV/remote/phone/window 
4 C  4  book/vase/car/chair 

, a

df.2 <- data.frame(loc = c('A','B','C'), str = c("book/chair/chair", " table/remote/vase ", "window")) 

, zawierające

loc      str 
1 A book/chair/car 
2 B table/remote/vase 
3 C     window 

Chcę utworzyć zmienną df.1$percentage który oblicza procenty elementów w df.1$str że są df.2$stredycji przez loc, czyli

loc person        str percentage 
1 A  1   door/window/table  0.00 
2 B  2 window/table/toilet/vase  0.50 
3 C  3 TV/remote/phone/window  0.25 
4 C  4  book/vase/car/chair  0.00 

(1 ma 0/3, 2/4 2 ma mecze, 3 ma 1/4, a 4 ma 0/4)

Dzięki!

+0

Czy pasujące elementy muszą mieć tę samą lokalizację? – Edward

+0

Przepraszam, tak. dopasuj ciągi znaków za pomocą 'loc'. Zmieniłem to pytanie. – Lucarno

Odpowiedz

4

Jak pewnie wiesz, data.frame kolumny mogą również posiadają listy (patrz Create a data.frame where a column is a list). Więc można podzielić str na listach słów:

df.1 <- transform(df.1, words.1 = I(strsplit(as.character(str), "/"))) 
df.2 <- transform(df.2, words.2 = I(strsplit(as.character(str), "/"))) 

następnie scalić swoje dane:

m <- merge(df.1, df.2, by = "loc") 

i prosto obliczyć procent użyciu mapply:

transform(m, percentage = mapply(function(x, y) sum(x%in%y)/length(x), 
           words.1, words.2)) 
4

Ktoś może prawdopodobnie pochodzić z inteligentniejsze rozwiązanie, ale tutaj jest to proste podejście:

library(data.table) 
dt1 = data.table(df.1, key = "loc") # set the key to match by loc 
dt2 = data.table(df.2) 

dt1[, percentage := dt1[dt2][, # merge 
      # clean up spaces and convert to strings 
      `:=`(str = gsub(" ", "", as.character(str)), 
       str.1 = gsub(" ", "", as.character(str.1)))][, 
      # calculate the percentage for each row 
      lapply(1:.N, function(i) { 
       tmp = strsplit(str, "/")[[i]]; 
       sum(tmp %in% strsplit(str.1, "/")[[i]])/length(tmp) 
      }) 
    ]] 

dt1 
# loc person        str percentage 
#1: A  1   door/window/table   0 
#2: B  2 window/table/toilet/vase   0.5 
#3: C  3 TV/remote/phone/window  0.25 
#4: C  4  book/vase/car/chair   0 
2

Alternatywnie,

test <- data.frame(str1 = df.1[1:nrow(df.2),]$str, str2 = df.2$str) 
df.1$percent <- NA 
getwords <- function(x) { gsub(" ","",unlist(strsplit(as.character(x),"/"))) } 
percent <- function(x,y) { 
sum(!is.na(unlist(sapply(getwords(x), function (d) grep(d, getwords(y))))))/ 
length(getwords(x)) 
} 
df.1[1:nrow(df.2),]$percent <- apply(test, 1, function(x) percent(x[1],x[2])) 

> df.1 
     loc person        str percent 

# A  1   door/window/table 0.00 
# B  2 window/table/toilet/vase  0.50 
# C  3 TV/remote/phone/window 0.25 
# C  4  book/vase/car/chair  NA 
Powiązane problemy