J'ai le cadre de données comme suit:
S A B C D E F 1 N N N N N N 2 N Y Y N N N 3 Y N Y N N N 4 Y N Y Y Y Y
où dois-je créer une nouvelle colonne F qui contient le caractère le plus d'occurrences des multiples colonnes A, B, C, D et E?
La sortie doit ressembler à ce qui suit:
S A B C D E 1 N N N N N 2 N Y Y N N 3 Y N Y N N 4 Y N Y Y Y
4 Réponses :
Nous pouvons créer une fonction Mode et l'appliquer sur les lignes
df1 <- structure(list(S = 1:4, A = c("N", "N", "Y", "Y"), B = c("N",
"Y", "N", "N"), C = c("N", "Y", "Y", "Y"), D = c("N", "N", "N",
"Y"), E = c("N", "N", "N", "Y")), class = "data.frame", row.names = c(NA,
-4L))
Ou une autre option est
c("Y", "N")[(str_count(do.call(paste0, df1[-1]), "N") > 2) + 1]
Une possibilité dplyr pourrait être:
df$F <- ifelse(rowMeans(df[2:length(df)] == "N") > 0.5, "N", "Y")
Cela suppose qu'il n'y a que N et Y valeurs et que le nombre de colonnes est 5.
Comme @Sotos l'a noté, il pourrait être facilement réécrit sous la forme base R :
df %>% mutate(F = ifelse(rowMeans(.[2:length(.)] == "N") > 0.5, "N", "Y"))
+1 Excellente idée, en évitant le apply () avec la marge 1 . Cela aurait pu être bien mieux si vous n'aviez pas chargé dplyr juste pour le tube et mutate . Laissez-le simplement dans la base R. De plus, vous pouvez également rendre 2 dynamique. Quelque chose comme plafond (ncol (df) / 2)
vous pouvez utiliser rowMeans (...)> 0.5 pour éviter de faire une hypothèse sur le nombre de colonnes
Une alternative, légèrement différente:
x$F <- unlist(do.call(Map, c(function(...) names(sort(-table(c(...)), partial=1)[1]), x[,-1]))) x # S A B C D E F # 1 1 N N N N N N # 2 2 N Y Y N N N # 3 3 Y N Y N N N # 4 4 Y N Y Y Y Y
Peut-être que j'essaie juste de produire du code obscur maintenant ...
Je réalise que cela pourrait être plus général que absolument nécessaire. Ceci trouve la "chose" la plus fréquente quel que soit le nombre de choses différentes qui existent entre les lignes.
Le sort (..., partial = 1) arrête le tri après le premier passage .
Ou :
d <- read.table(text ="S A B C D E 1 N N N N N 2 N Y Y N N 3 Y N Y N N 4 Y N Y Y Y", header = TRUE, row.names = 1, stringsAsFactors = FALSE) d$F <- with( stack(data.frame(t(as.matrix(d)), stringsAsFactors = FALSE)), tapply(values, ind, function(x) names(sort(table(x), decreasing = TRUE)[1]))) d #A B C D E F #1 N N N N N N #2 N Y Y N N N #3 Y N Y N N N #4 Y N Y Y Y Y