2010-02-10 5 views
3

J'utilise R, et je suis un débutant. J'ai deux grandes listes (30K éléments chacun). On est appelé descriptions et où chaque élément est (peut-être) une chaîne de tokenized. L'autre est appelé probes où chaque élément est un nombre. Je dois faire un dictionnaire qui mappe probes à quelque chose dans descriptions, si ce quelque chose est là. Voici comment je vais à ce sujet:Remplacement R-thonic pour simple pour les boucles contenant une condition

probe2gene <- list() 
for (i in 1:length(probes)){ 
strings<-strsplit(descriptions[i]), '//') 
if (length(strings[[1]]) > 1){ 
    probe2gene[probes[i]] = strings[[1]][2] 
} 
} 

Ce qui fonctionne très bien, mais il semble lent, beaucoup plus lent que le python à peu près équivalent:

probe2gene = {} 
for p,d in zip(probes, descriptions): 
    try: 
    probe2gene[p] = descriptions.split('//')[1] 
    except IndexError: 
    pass 

Ma question: est-il un « R-thonic » façon de faire ce que je suis en train de faire? Le R manual entry on for loops suggère que de telles boucles sont rares. Y a-t-il une meilleure solution?

Edit: typique bonne "description" ressemble à ceci:

"NM_009826 // Rb1cc1 // RB1-inducible coiled-coil 1 // 1 A2 // 12421 /// AB070619 // Rb1cc1 // RB1-inducible coiled-coil 1 // 1 A2 // 12421 /// ENSMUST00000027040 // Rb1cc1 // RB1-inducible coiled-coil 1 // 1 A2 // 12421" 

une mauvaise « description: ressemble à ce

"-----" 

mais il peut facilement être un autre non-very- Chaîne utile: chaque sonde est simplement un nombre Les vecteurs probe et description ont la même longueur, et correspondent complètement l'un à l'autre, c'est-à-dire probe[i] et

+0

"R-thonic" :) Ça ne devrait pas être Ric? – Skilldrick

+0

Un petit échantillon de données serait utile. – Shane

+1

C'est définitivement "piraté". – Harlan

Répondre

3

Il est généralement préférable dans R si vous utilisez les différentes fonctions de type application, plutôt qu'une boucle. Je pense que cela résout votre problème; le seul inconvénient est que vous devez utiliser des clés de chaîne.

> descriptions <- c("foo//bar", "") 
> probes <- c(10, 20) 
> probe2gene <- lapply(strsplit(descriptions, "//"), function (x) x[2]) 
> names(probe2gene) <- probes 
> probe2gene <- probe2gene[!is.na(probe2gene)] 
> probe2gene[["10"]] 
[1] "bar" 

Malheureusement, R n'a pas un bon dictionnaire/type de carte. Le plus proche que j'ai trouvé est l'utilisation de listes comme une carte de chaîne à valeur. Cela semble être idiomatique, mais c'est moche.

+0

Merci! C'est beaucoup plus rapide. Avait réalisé des choses comme "strsplit" pourrait être appliqué à des vecteurs entiers. Soigné! –

2

Si je comprends bien, vous cherchez à sauvegarder chaque combinaison sonde-description où il y a plus d'une valeur (fractionnée) dans la description?

La sonde et la description ont-elles la même longueur?

C'est un peu désordonné mais un premier passage rapide?

a <- list("a","b","c") 
b <- list(c("a","b"),c("DEF","ABC"),c("Z")) 

names(b) <- a 
matches <- which(lapply(b, length)>1) #several ways to do this 
b <- lapply(b[matches], function(x) x[2]) #keeps the second element only 

C'est ma première tentative. Si vous avez un exemple de jeu de données qui serait très utile.

Meilleures salutations,

Jay

+0

Il est difficile d'être le premier intervenant;) – Jay

0

Une autre façon.

probe<-c(4,3,1) 
gene<-c('red//hair','strange','blue//blood') 
probe2gene<-character() 
probe2gene[probe]<-sapply(strsplit(gene,'//'),'[',2) 
probe2gene 
[1] "blood" NA  NA  "hair" 

Dans le sapply, nous profitons du fait que, dans R l'opérateur est également subsetting une fonction nommée « [ » auquel nous pouvons passer l'index comme un argument. En outre, un index hors plage ne provoque pas d'erreur mais donne une valeur NA. Sur la gauche de la même ligne, nous utilisons le fait que nous pouvons passer un vecteur d'indices dans n'importe quel ordre et avec des lacunes.

0

Voici une autre approche qui devrait être rapide. Notez que cela ne supprime les descriptions vides.Il pourrait être adapté pour faire cela ou vous pouvez nettoyer ceux dans une étape de post-traitement en utilisant lapply. Est-ce le cas que vous n'aurez jamais une description valide de longueur?

make_desc <- function(n) 
{ 
    word <- function(x) paste(sample(letters, 5, replace=TRUE), collapse = "") 
    if (runif(1) < 0.70) 
     paste(sapply(seq_len(n), word), collapse = "//") 
    else 
     "----" 
} 

description <- sapply(seq_len(10), make_desc) 
probes <- seq_len(length(description)) 

desc_parts <- strsplit(description, "//", fixed=TRUE, useBytes=TRUE) 
lens <- sapply(desc_parts, length) 
probes_expand <- rep(probes, lens) 
ans <- split(unlist(desc_parts), probes_expand) 


> description 
[1] "fmbec"                
[2] "----"                 
[3] "----"                 
[4] "frrii//yjxsa//wvkce//xbpkc"           
[5] "kazzp//ifrlz//ztnkh//dtwow//aqvcm"         
[6] "stupm//ncqhx//zaakn//kjymf//swvsr//zsexu"        
[7] "wajit//sajgr//cttzf//uagwy//qtuyh//iyiue//xelrq"      
[8] "nirex//awvnw//bvexw//mmzdp//lvetr//xvahy//qhgym//ggdax"    
[9] "----"                 
[10] "ubabx//tvqrd//vcxsp//rjshu//gbmvj//fbkea//smrgm//qfmpy//tpudu//qpjbu" 


> ans[[3]] 
[1] "----" 
> ans[[4]] 
[1] "frrii" "yjxsa" "wvkce" "xbpkc"