2012-02-02 130 views
2

我有一個3列數據幀,看起來有點像這樣的建築,距離匹配值的列表:R:在data.frame

id  name links 
1 134235 dave "34657","34563","23459" 
2 23459 mary "134235","45868","45677" 
3 165432 jane "134235","23459","44657" 

其中id和name值是唯一的,而且鏈接是一個字符串表示與每行中某些名稱的關聯的ID。因此,例如戴夫包括鏈接ID 23459這是瑪麗,所以戴夫連接到瑪麗。我需要產生的數據中的所有連接的一對列表,以便與示例數據我想輸出是這樣的:用方法做這樣apply纔去

dave,mary 
mary,dave 
jane,dave 
jane,mary 

很新的R和看到令人驚奇的事情並試圖複製一個解決方案,看起來更像是一個JavaScript例程,效率非常低,我想知道是否有人可以提供幫助。

回答

1

的一個解決方案,使用馬特的dput():

tab <- structure(list(
    id = c("134235", "23459", "165432"), 
    name = c("dave", "mary", "jane"), 
    links = c("'34657', '34563', '23459'", 
      "'134235', '45868', '45677'", 
      "'134235', '23459', '44657'")), 
    .Names = c("id", "name", "links"), 
    row.names = c(NA, -3L), class = "data.frame") 

conns <- function(name, links) { 
    paste(name, tab$name[tab$id %in% as.numeric(unlist(strsplit(gsub('\'|\"', 
    '', links), ',')))], sep=',') 
} 

connections <- unname(unlist(mapply(conns, tab$name, tab$links, 
    SIMPLIFY=FALSE))) 
+1

<驚呆了......那麼這真是太棒了!我知道R很強大,但是這讓它進入了另一個聯盟。所以我可以從這個mapply中學習如何運行函數conns,在每一行tab上做一些名字和鏈接(從這裏返回的是未列出的和未命名的)。在每個「鏈接」的conns中,您分割並查看每個id是否在其中。如果是這種匹配是用來返回名稱。 – mhawksey 2012-02-02 08:58:53

+0

mhawksey,令人印象深刻的使用單個子句中的'i'開頭的所有兩個字母單詞(好的,您使用變量'id',但它是我使用谷歌搜索找到的最接近的例子之一)。 – Kylos 2014-01-09 19:42:02

0
dat<- structure(list(
    id = c("134235", "23459", "165432"), 
    name = c("dave", "mary", "jane"), 
    links = c("'34657', '34563', '23459'", 
       "'134235', '45868', '45677'", 
       "'134235', '23459', '44657'")), 
    .Names = c("id", "name", "links"), 
    row.names = c(NA, -3L), class = "data.frame") 


# It can all be done in base, of course... 
library(stringr) 
library(reshape2) 

# This would be easy to do if links weren't in that format - 
# one record per id-link pair would be preferable. 
# Split dat$links and remove any quotes 
dat.wider <- data.frame(
    dat[ , c("id", "name")], 
    str_split_fixed(string = gsub(dat$links, 
            pattern = "['|\"]", 
            replace = ""), 
        pattern = ", ", 
        n = 3) 
) 

# Reshape 
dat.long <- melt(dat.wider, id.var = c("id", "name")) 

# Self-join - this is not quite the right method, but I'm just not 
# thinking straight right now 
dat.joined <- unique(merge(x = dat.long[ , c("name", "value")], 
          y = dat.long[ , c("id", "name")], 
          by.x = "value", 
          by.y = "id" 
)) 

# And, finally, if you wanted vector output... 
res <- with(dat.joined, paste(name.x, name.y, sep = ", ")) 
0

第一步應正常化的數據,特別地,解析字符串。 您可以使用ddply:它應用了一個函數 ,該函數接收一個data.frame塊(在我們的例子中爲一行) 並以某種方式轉換它。你只需要編寫一個函數 ,它可以在一行上工作,即在一個字符串上工作。

# Sample data 
n <- 10 
k <- 3 
ids <- as.character(unique(round(1e5*runif(n)))) 
n <- length(ids) 
names <- LETTERS[1:n] 
links <- lapply(ids, function(u) 
    sample(setdiff(ids,u),k,replace=FALSE)) 
links <- sapply(links, function(u) 
    paste('"', paste(u,collapse='","'), '"', sep="")) 
d <- data.frame( 
    id=ids, 
    name=names, 
    links=links, 
    stringsAsFactors=FALSE 
) 

library(plyr) 
library(stringr) 
dd <- ddply( 
    d, 
    c("id", "name"), 
    function(u) data.frame(
    id=u$id, 
    name=u$name, 
    link=unlist(str_split(str_replace_all(u$links, '"', ''), ",")) 
)) 

然後,您可以加入的數據,無論是與mergesqldf

library(sqldf) 
sqldf(" 
    SELECT A.name, B.name 
    FROM dd AS A, d AS B 
    WHERE A.link = B.id 
")