2010-10-12 4 views
4

J'ai une base de données avec des millions de lignes et trois colonnes intitulées Mots-clés, Impressions, Clics. Je voudrais ajouter une colonne avec des valeurs en fonction de l'évaluation de cette fonction:Ajout d'une colonne basée sur d'autres valeurs

isType <- function(Impressions, Clicks) 
{ 
if (Impressions >= 1 & Clicks >= 1){return("HasClicks")} else if (Impressions >=1 & Clicks == 0){return("NoClicks")} else {return("ZeroImp")} 
} 

jusqu'ici tout va bien. J'essaye alors ceci pour créer la colonne mais 1) il prend pour toujours et 2) il marque toutes les rangées a "HasClicks" même ceux où il ne devrait pas.

# Creates a dataframe 
Type <- data.frame() 
# Loops until last row and store it in data.frame 
for (i in c(1:dim(Mydf)[1])) {Type <- rbind(Type,isType(Mydf$Impressions[i], Mydf$Clicks[i]))} 
# Add the column to Mydf 
Mydf <- transform(Mydf, Type = Type) 
données d'entrée

:

Mots-clés, impressions, clics
"Bonjour", 0,0
"Monde", 1,0
"R", 34,23

Mots-clés, Impressions, Clics, Type "Monde", 1,0, "NoClicks"
"R", 34,23, "HasClicks"

Répondre

10

Miser sur la solution de Joshua, je trouve plus propre à générer type en un seul coup (note cependant que cela suppose Clicks> = 0 ...)

Mydf$Type = ifelse(Mydf$Impressions >= 1, 
    ifelse(Mydf$Clicks >= 1, 'HasClicks', 'NoClicks'), 'ZeroImp') 
+0

Merci! Je suis arrivé à la même conclusion que ifelse devait être utilisé. Je suis trop nouveau pour R pour comprendre pourquoi mais merci! – datayoda

+0

@datayoda: 'if()' n'autorise qu'une seule condition. C'est à dire. il permet, ou utilise, seulement un seul VRAI ou FAUX. Dans votre code, vous obteniez beaucoup de valeurs TRUE/FALSE et seul le premier serait utilisé. Dans une clause 'if()', vous ne devriez pas non plus utiliser '&' car il est vectorisé et fait la comparaison pour chaque élément des vecteurs associés. '&&' sert à comparer des valeurs uniques. Comparez: 'runif (10)> 0.5 & runif (10)> 0.3' avec' runif (10)> 0.5 && runif (10)> 0.3'. Si une ou plusieurs versions de la première version sont FALSE, la seconde ('&&') retournera une FALSE globale. 'ifelse' est un' if' vectorisé. –

3

D'abord, le cas/bloc d'autre dans votre fonction retourne l'avertissement:

Message d'avertissement:
Dans le cas (1: 2> 2: 3) TRUE sinon FALSE:
la condition a une longueur> 1 et seul le premier élément sera utilisé

ce qui explique pourquoi il toutes les lignes sont le même. Deuxièmement, vous devez allouer votre data.frame et remplir les éléments plutôt que de combiner plusieurs fois les objets ensemble. J'imagine que cela cause vos longues périodes de temps.

EDIT: Mon code partagé. J'aimerais que quelqu'un apporte une solution plus élégante.

Mydf <- data.frame(
    Keywords = sample(c("Hello","World","R"),20,TRUE), 
    Impressions = sample(0:3,20,TRUE), 
    Clicks = sample(0:3,20,TRUE)) 

Mydf$Type <- "ZeroImp" 
Mydf$Type <- ifelse(Mydf$Impressions >= 1 & Mydf$Clicks >= 1, 
    "HasClicks", Mydf$Type) 
Mydf$Type <- ifelse(Mydf$Impressions >= 1 & Mydf$Clicks == 0, 
    "NoClicks", Mydf$Type) 
+0

Pourriez-vous un code? – datayoda

0

C'est un cas où l'arithmétique peut être plus propre et probablement plus rapide que les instructions ifelse imbriquées.

construction de nouveau sur la solution de Joshua:

Mydf$Type <- factor(with(Mydf, (Impressions>=1)*2 + (Clicks>=1)*1), 
        levels=1:3, labels=c("ZeroImp","NoClicks","HasClicks")) 
Questions connexes