1
votes

Rechercher des valeurs de colonne partagées entre d'autres valeurs de colonne R

J'ai le df suivant qui montre la nourriture que certaines personnes mangent pendant une journée.

df = data.frame("Name" = c("Brian", "Brian", "Brian",
                       "Alice", "Alice", "Alice",
                       "Paul", "Paul", "Paul",
                       "Clair", "Clair", "Clair"),
            "Meal" = c("Breakfast", "Lunch", "Dinner",
                       "Breakfast", "Lunch", "Dinner",
                       "Breakfast", "Lunch", "Dinner",
                       "Breakfast", "Lunch", "Dinner"),
            "Food" = c("Waffle", "Chicken", "Steak",
                       "Waffle", "Soup", "Steak",
                       "Waffle", "Chicken", "Chicken",
                       "Waffle", "Soup", "Chicken")

Je veux trouver un aliment qui a été mangé par 100% des gens, un aliment qui a été mangé par 75% des gens, et un aliment consommé par 50% des gens. Dans ce cas, la gaufre a été mangée par tout le monde, le poulet a été mangé par 75% des personnes et la soupe / steak a été mangée par 50% des personnes.

MODIFIER:
Résultat attendu: le pourcentage de personnes qui ont mangé chaque aliment
Gaufre - 100%
Poulet - 75%
Steak - 50%
Soupe - 50%.


0 commentaires

5 Réponses :


0
votes

Edit: Avec la sortie attendue expliquée

Modes <- function(x) {
  ux <- unique(x)
  tab <- tabulate(match(x, ux))
  ux[tab == max(tab)]
}

aggregate(Food ~ Meal, df, function(x) levels(x)[Modes(x)] )

       Meal           Food
1 Breakfast         Waffle
2    Dinner Steak, Chicken
3     Lunch  Chicken, Soup

Anciennes réponses


Vous devriez donner une sortie attendue car cette question n'est pas claire. Voici un code pour réorganiser vos données sous une forme que vous trouverez plus adaptée aux statistiques calculées.

aggregate(Food ~ Meal, df, table)

      Meal Food.Chicken Food.Soup Food.Steak Food.Waffle
1 Breakfast            0         0          0           4
2    Dinner            2         0          2           0
3     Lunch            2         2          0           0

pour trouver la nourriture la plus populaire à chaque repas

apply(aggregate(Food ~ Name, df, table)[-1],2, function(x) sum(x!=0)/length(x))*100

Food.Chicken    Food.Soup   Food.Steak  Food.Waffle 
          75           50           50          100 

Crédit pour la fonction Modes


9 commentaires

Je pense OP recherche colMeans (avec (unique (df [ c ("Name", "Food")]), table (Name, Food)))


La colonne repas n'a pas d'importance. Le but est de trouver des similitudes dans la nourriture que les gens mangent, et s'il y a un aliment mangé par tout le monde / un aliment mangé par la plupart des gens. Quel que soit le repas, il a été mangé. Désolé pour la confusion.


Vous devez encore mettre une sortie attendue .. Mais j'ai ajouté à ma réponse. J'espère que cela aide


Désolé, c'est la première fois que je pose une question. J'ai ajouté la sortie attendue


La réponse de @markus est ce que je recherche! Marquer cette question comme réponse même si la réponse se trouve dans les commentaires. Merci tout le monde!


Si réduit à sa structure de base appliquer (agrégat (Aliment ~ Nom, df, table) [- 1], 2, fonction (x) somme (x! = 0) / longueur (x)) * 100 ressemble étrangement à apply (aggregate (Food ~ Name, df, function (x) ifelse (table (x) == 0, 0, 1)) [- 1], 2, sum) . Vous pourriez / devriez au moins créditer ma réponse comme étant un point de départ pour votre réponse.


@ChrisRuehlemann, me semble assez différent. Ignorer l'agrégat qui a été dans toutes mes réponses, apply est une approche courante pour les opérations par colonne / ligne. Nos fonctions (x) sont totalement différentes et ont des sorties différentes.


Non, ce n'est pas l'utilisation de aggregate ou apply par eux-mêmes, mais la façon dont ils sont intégrés les uns dans les autres est très similaire


@ChrisRuehlemann La fonction personnalisée pour l'un est dans apply et pour l'autre est dans agrégat donc l'implémentation est assez différente.



0
votes

Est-ce ce que vous voulez?

apply(aggregate(Food ~ Name, df, function(x) ifelse(table(x) == 0, 0, 1))[-1], 2, 
      function(x)  ifelse(sum(x) == length(unique(df$Name)), "100%",  
                          ifelse(sum(x) == length(unique(df$Name)) - 1, "75%",
                                 ifelse(sum(x) == length(unique(df$Name)) - 2, "50%", 
                                        ifelse(sum(x) == length(unique(df$Name)) - 3, "25%", "0%")))))
Food.Chicken    Food.Soup   Food.Steak  Food.Waffle 
       "75%"        "50%"        "50%"       "100%" 

Ou préférez-vous ceci?

apply(aggregate(Food ~ Name, df, function(x) ifelse(table(x) == 0, 0, 1))[-1], 2, sum)
Food.Chicken    Food.Soup   Food.Steak  Food.Waffle 
           3            2            2            4 


3 commentaires

Je viens de commenter l'autre réponse, mais le repas auquel la nourriture a été mangée n'a pas d'importance. Je veux juste voir s'il y a un aliment qui a été mangé par tout le monde, ou un aliment qui vient d'être mangé par la plupart des gens. Quel que soit le repas, il a été mangé. Désolé pour la confusion.


Cela ressemble à une version compliquée de table (df $ Food) qui donne une erreur erronée pour le poulet. Il y a 4 cas de poulet.


Regardez ce que dit OP!



1
votes

Vous pouvez utiliser dplyr et janitor:

    Food Alice Brian Clair Paul Percent
 Chicken     0     1     1    1     75%
    Soup     1     0     1    0     50%
   Steak     1     1     0    0     50%
  Waffle     1     1     1    1    100%

Cela vous donne:

    Food Percent
 Chicken     75%
    Soup     50%
   Steak     50%
  Waffle    100%


0 commentaires

2
votes
df <- data.frame("Name" = c("Brian", "Brian", "Brian",
                           "Alice", "Alice", "Alice",
                           "Paul", "Paul", "Paul",
                           "Clair", "Clair", "Clair"),
                "Meal" = c("Breakfast", "Lunch", "Dinner",
                           "Breakfast", "Lunch", "Dinner",
                           "Breakfast", "Lunch", "Dinner",
                           "Breakfast", "Lunch", "Dinner"),
                "Food" = c("Waffle", "Chicken", "Steak",
                           "Waffle", "Soup", "Steak",
                           "Waffle", "Chicken", "Chicken",
                           "Waffle", "Soup", "Chicken")
)     

0 commentaires

2
votes

Voici une approche qui utilise table :

x <- ((with(df, table(Food, Name)) >= 1) + 0)
## OR x <- table(unique(df[, c("Food", "Name")]))
x
#          Name
# Food      Alice Brian Clair Paul
#   Chicken     0     1     1    1
#   Soup        1     0     1    0
#   Steak       1     1     0    0
#   Waffle      1     1     1    1
rowSums(x)/ncol(x)
# Chicken    Soup   Steak  Waffle 
#    0.75    0.50    0.50    1.00 


0 commentaires