2012-02-02 9 views
2

に一致する値からリストを構築:R:私は少しこのようになります3列のデータフレームを持ってdata.frame

idとnameの値が一意である、とのリンクが文字列である
id  name links 
1 134235 dave "34657","34563","23459" 
2 23459 mary "134235","45868","45677" 
3 165432 jane "134235","23459","44657" 

各行のいくつかの名前との関連付けを示すIDの名前。たとえば、daveにはmaryというリンクid 23459が含まれていますので、daveはmaryに接続しています。

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

非常Rへの新規およびapplyのような方法でと行く前に行わ驚くべきことを見た:私は何を生産するために必要なことは、私のような出力何かだろう例のデータを持つようにデータのすべての接続のペアリストであります私は誰かが助けることができるかどうか疑問に思いました。マットのdput()を使用して

答えて

1

一つの解決策は、:

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内で分割し、各IDがその中にあるかどうかを確認します。一致する場合は、この一致を使用して名前を返します。 – mhawksey

+0

mhawksey、1つの句に 'i'で始まる2文字の単語を使用しています(これは変数 'id'を使用していますが、Google検索で最も近い例の1つです)。 – Kylos

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(ここでは1行)のチャンクを取り、 を何らかの方法で変換します。 1つの行、つまり1つの文字列に作用する関数 を書くだけでいいです。

# 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, '"', ''), ",")) 
)) 

あなたは、どちらのmergeまたはsqldfで、データを結合することができます。

library(sqldf) 
sqldf(" 
    SELECT A.name, B.name 
    FROM dd AS A, d AS B 
    WHERE A.link = B.id 
") 
関連する問題