2013-05-29 21 views
6

Ben iki veri çerçeveleri var arasındaki maçları: BöyleceSayım iki dizeleri

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")) 

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 

Ve verir

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

,

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

Ben loc tarafından df.2$strdüzenlemek içindedir ya da bu df.1$str elemanların yüzdelerini hesaplar bir değişken df.1$percentage oluşturmak istiyorum: 2 2/4 maçları, 3 sahiptir

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, 0/3 vardır 1/4 ve 4, 0/4)

'a sahiptir.

Teşekkürler!

+0

Eşleşen öğeler aynı konuma sahip mi? – Edward

+0

Üzgünüz, evet. 'loc' kullanarak dizeleri eşleştir. Soruyu düzenledim. – Lucarno

cevap

4

, data.frame sütunları da tutabilir listeleri (Create a data.frame where a column is a list bakınız).

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

verilerinizi Sonra birleştirme:: Yani kelime listeleri halinde str ayırabilirsiniz

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

Ve basitçe mapply kullanarak yüzdesini hesaplamak:

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

Biri muhtemelen daha akıllı bir çözüm ile gelebilir, ama burada basit bir yaklaşım:

Bildiğiniz gibi
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

alternatif yol,

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