J'essaie d'ajouter une nouvelle colonne à un cadre de données en fonction de plusieurs conditions d'autres colonnes. J'ai les données suivantes:
> commute <- c("walk", "bike", "subway", "drive", "ferry", "walk", "bike", "subway", "drive", "ferry", "walk", "bike", "subway", "drive", "ferry")
> kids <- c("Yes", "Yes", "No", "No", "Yes", "Yes", "No", "No", "Yes", "Yes", "No", "No", "Yes", "No", "Yes")
> distance <- c(1, 12, 5, 25, 7, 2, "", 8, 19, 7, "", 4, 16, 12, 7)
>
> df = data.frame(commute, kids, distance)
> df
commute kids distance
1 walk Yes 1
2 bike Yes 12
3 subway No 5
4 drive No 25
5 ferry Yes 7
6 walk Yes 2
7 bike No
8 subway No 8
9 drive Yes 19
10 ferry Yes 7
11 walk No
12 bike No 4
13 subway Yes 16
14 drive No 12
15 ferry Yes 7
Si les trois conditions suivantes sont remplies:
commute = walk OR bike OR subway OR ferry
AND
kids = Yes
AND
distance is less than 10
Ensuite, j'aimerais qu'une nouvelle colonne appelée get.flyer soit égale à "Oui". Le bloc de données final devrait ressembler à ceci:
commute kids distance get.flyer
1 walk Yes 1 Yes
2 bike Yes 12 Yes
3 subway No 5
4 drive No 25
5 ferry Yes 7 Yes
6 walk Yes 2 Yes
7 bike No
8 subway No 8
9 drive Yes 19
10 ferry Yes 7 Yes
11 walk No
12 bike No 4
13 subway Yes 16 Yes
14 drive No 12
15 ferry Yes 7 Yes
Nous pouvons utiliser %in%
pour comparer plusieurs éléments d'une colonne, &
pour vérifier si les deux conditions sont VRAI.
library(dplyr)
df %>%
mutate(get.flyer = c("", "Yes")[(commute %in% c("walk", "bike", "subway", "ferry") &
as.character(kids) == "Yes" &
as.numeric(as.character(distance)) < 10)+1] )
Il est préférable de créer le data.frame
avec stringsAsFactors=FALSE
car il s'agit par défaut de TRUE
. Si nous vérifions la str(df)
, nous pouvons constater que toutes les colonnes sont des classes factor
. De même, s'il existe des valeurs manquantes, vous pouvez utiliser NA
au lieu de ""
pour éviter de convertir la class
d'une colonne numeric
en quelque chose d'autre.
Si nous réécrivons la création de 'df'
distance <- c(1, 12, 5, 25, 7, 2, NA, 8, 19, 7, NA, 4, 16, 12, 7)
df1 <- data.frame(commute, kids, distance, stringsAsFactors=FALSE)
le code ci-dessus peut être simplifié
df1 %>%
mutate(get.flyer = c("", "Yes")[(commute %in% c("walk", "bike", "subway", "ferry") &
kids == "Yes" &
distance < 10)+1] )
Pour une meilleure compréhension, certaines personnes préfèrent ifelse
df1 %>%
mutate(get.flyer = ifelse(commute %in% c("walk", "bike", "subway", "ferry") &
kids == "Yes" &
distance < 10,
"Yes", ""))
Cela peut aussi être fait facilement avec les méthodes base R
df1$get.flyer <- with(df1, ifelse(commute %in% c("walk", "bike", "subway", "ferry") &
kids == "Yes" &
distance < 10,
"Yes", ""))
La solution est déjà indiquée par @akrun. Je voudrais le présenter d'une manière plus "enveloppée".
Vous pouvez utiliser l'instruction ifelse
pour créer une colonne en fonction d'une ou de plusieurs conditions. Mais vous devez d’abord changer le «codage» des valeurs manquantes dans la colonne de distance. Vous avez utilisé ""
pour indiquer une valeur manquante. Toutefois, la colonne entière est convertie en string
et empêche la comparaison numérique (distance < 10
n'est pas possible). La manière R
d'indiquer une valeur manquante est NA
, votre définition de colonne de distance
devrait être:
distance <- c(1, 12, 5, 25, 7, 2, NA, 8, 19, 7, NA, 4, 16, 12, 7)
La déclaration ifelse
ressemble alors à ceci:
df$get.flyer <- ifelse(
(
(df$commute %in% c("walk", "bike", "subway", "ferry")) &
(df$kids == "Yes") &
(df$distance < 10)
),
1, # if condition is met, put 1
0 # else put 0
)
Facultatif: Pensez également à coder vos autres colonnes différemment:
TRUE
et FALSE
au lieu de "Oui" et "Non" pour la variable kids
factor
pour faire la navetteExemple, vérifiez si first_column_name est contenu dans second_column_name et écrivez le résultat dans new_column
df$new_column <- apply(df, 1, function(x) grepl(x['first_column_name'], x['second_column_name'], fixed = TRUE))
Détails:
df$new_column <- # create a new column with name new_column on df
apply(df, 1 # `1` means for each row, `apply(df` means apply the following function on df
function(x) # Function definition to apply on each row, `x` means input row for each row.
grepl(x['first_column_name'], x['second_column_name'], fixed = TRUE)) # Body of function to apply, basically run grepl to find if first_column_name is in second_column_name, fixed = TRUE means don't use regular expression just the plain text from first_column_name.