(J'ai le sentiment que je vais me sentir vraiment stupide après avoir obtenu une réponse, mais je ne pouvais tout simplement pas comprendre.)

J'ai un data.frame avec une colonne vide à la fin. Il sera principalement rempli de NA, mais je souhaite en remplir certaines lignes avec une valeur. Cette colonne représente une estimation des données manquantes dans l'une des colonnes du data.frame.

Mon data.frame initial ressemble à ceci:

Game | Rating | MinPlayers | MaxPlayers | MaxPlayersGuess
---------------------------------------------------------
A    | 6      | 3          | 6          |
B    | 7      | 3          | 7          |
C    | 6.5    | 3          | N/A        |median(df$MaxPlayers[df$MinPlayers ==3,])
D    | 7      | 3          | 6          |
E    | 7      | 3          | 5          |
F    | 9.5    | 2          | 5          |
G    | 6      | 2          | 4          |
H    | 7      | 2          | 4          |
I    | 6.5    | 2          | N/A        |median(df$MaxPlayers[df$MinPlayers ==2,])
J    | 7      | 2          | 2          |
K    | 7      | 2          | 4          |

Notez que deux des lignes ont "N / A" pour MaxPlayers. Ce que j'essaie de faire, c'est d'utiliser les informations dont je dispose pour deviner ce que pourraient être les MaxPlayers. Si la médiane (MaxPlayers) pour les jeux à 3 joueurs est de 6, MaxPlayerGuess doit être égal à 6 pour les jeux avec MinPlayers == 3 et MaxPlayers == N / A. (J'ai essayé d'indiquer dans le code la valeur que MaxPlayerGuess devrait obtenir dans l'exemple ci-dessus.)

Le data.frame résultant ressemblerait à ceci:

Game | Rating | MinPlayers | MaxPlayers | MaxPlayersGuess
---------------------------------------------------------
A    | 6      | 3          | 6          |
B    | 7      | 3          | 7          |
C    | 6.5    | 3          | N/A        |6
D    | 7      | 3          | 6          |
E    | 7      | 3          | 5          |
F    | 9.5    | 2          | 5          |
G    | 6      | 2          | 4          |
H    | 7      | 2          | 4          |
I    | 6.5    | 2          | N/A        |4
J    | 7      | 2          | 2          |
K    | 7      | 2          | 4          |

Pour partager les résultats d'une tentative:

gld$MaxPlayersGuess <- ifelse(is.na(gld$MaxPlayers), median(gld$MaxPlayers[gld$MinPlayers,]), NA)


Error in gld$MaxPlayers[gld$MinPlayers, ] : 
incorrect number of dimensions
r
0
Zelbinian 21 avril 2017 à 02:54

3 réponses

Meilleure réponse

Mise à jour par rapport à l'exemple publié.

Voici mon conseil du jour, il est parfois plus facile de calculer ce que vous voulez, puis de le saisir lorsque vous en avez besoin plutôt que d'utiliser toutes ces contigences logiques. Vous essayez de trouver un moyen de tout calculer en même temps et cela rend les choses déroutantes, divisez-les en étapes. Vous devez connaître la valeur médiane de "MaxPlayer" pour chaque groupe possible de "MinPlayer". Ensuite, vous souhaitez utiliser cette valeur lorsque MaxPlayer est manquant. Voici donc un moyen simple de le faire.

#generate fake data 
MinPlayer <- rep(3:2, each = 4)
MaxPlayer <- rep(2:5, each = 2, times = 2)

df <- data.frame(MinPlayer, MaxPlayer)

#replace some values of MaxPlayer with NA
df$MaxPlayer <- ifelse(df$MaxPlayer == 3, NA, df$MaxPlayer)

####STARTING DATA
# > df
# MinPlayer MaxPlayer
# 1          3         2
# 2          3         2
# 3          3        NA
# 4          3        NA
# 5          2         4
# 6          2         4
# 7          2         5
# 8          2         5
# 9          3         2
# 10         3         2
# 11         3        NA
# 12         3        NA
# 13         2         4
# 14         2         4
# 15         2         5
# 16         2         5

####STEP 1
#find the median of MaxPlayer for each group of MinPlayer (e.g., when MinPlayer == 1, 2 or whatever)
#just add a column to the data frame that has the right median value for each subset of MinPlayer in it and grab that value to use later. 
library(plyr) #plyr is a great way to compute things across data subsets
df <- ddply(df, c("MinPlayer"), transform, 
            median.minp = median(MaxPlayer, na.rm = TRUE)) #ignore NAs in the median

####STEP 2
#anytime that MaxPlayer == NA, grab the median value to replace the NA, otherwise keep the MaxPlayer value
df$MaxPlayer <- ifelse(is.na(df$MaxPlayer), df$median.minp, df$MaxPlayer)

####STEP 3
#you had to compute an extra column you don't really want, so drop it now that you're done with it
df <- df[ , !(names(df) %in% "median.minp")]

####RESULT
# > df
# MinPlayer MaxPlayer
# 1          2         4
# 2          2         4
# 3          2         5
# 4          2         5
# 5          2         4
# 6          2         4
# 7          2         5
# 8          2         5
# 9          3         2
# 10         3         2
# 11         3         2
# 12         3         2
# 13         3         2
# 14         3         2
# 15         3         2
# 16         3         2

Ancienne réponse ci-dessous ici ...

Veuillez poster un exemple reproductible !!

#fake data 
this <- rep(1:2, each = 1, times = 2)
that <- rep(3:2, each = 1, times = 2)

df <- data.frame(this, that)

Si vous posez simplement des questions sur l'indexation de base ... Par exemple, trouvez des valeurs où quelque chose remplit une condition, cela renverra les index de ligne des valeurs correspondant à la condition (rechercher? Laquelle):

> which(df$this < df$that)
[1] 1 3

Cela renverra la VALEUR des éléments correspondant à votre condition et non l'index de ligne - vous utilisez simplement l'index de ligne retourné par "which" pour trouver la valeur correspondante dans la colonne correcte de votre bloc de données (ici "this")

> df[which(df$this < df$that), "this"]
[1] 1 1

Si vous souhaitez appliquer un calcul lorsque «ceci» est «moins» que cela et ajouter une nouvelle colonne à votre bloc de données, utilisez simplement «ifelse». If else crée un vecteur logique où le truc correspond à votre condition, puis fait des trucs correspondant à votre condition (par exemple, où votre test logique == TRUE).

#if "this" is < "that", multiply by 2 
df$result <- ifelse(df$this < df$that, df$this * 2, NA)

> df
this that result
1    1    3      2
2    2    2     NA
3    1    3      2
4    2    2     NA

Sans un exemple reproductible, rien de plus ne peut être fourni.

2
griffmer 21 avril 2017 à 03:56

Si vous souhaitez utiliser dplyr, vous pouvez essayer:

Contribution:

df <- data.frame(
  Game = LETTERS[1:11],
  Rating = c(6,7,6.5,7,7,9.5,6,7,6.5,7,7),
  MinPlayers = c(rep(3,5), rep(2,6)),
  MaxPlayers = c(6,7,NA,6,5,5,4,4,NA,2,4)     
)

Processus:

df %>% 
  group_by(MinPlayers) %>%
  mutate(MaxPlayers = if_else(is.na(MaxPlayers), median(MaxPlayers, na.rm=TRUE), MaxPlayers))

Cela regroupe la base de données MinPlayers, puis attribue une valeur médiane de MaxPlayers aux lignes avec des données manquantes.

Production:

Source: local data frame [11 x 4]
Groups: MinPlayers [2]

     Game Rating MinPlayers MaxPlayers
   <fctr>  <dbl>      <dbl>      <dbl>
1       A    6.0          3          6
2       B    7.0          3          7
3       C    6.5          3          6
4       D    7.0          3          6
5       E    7.0          3          5
6       F    9.5          2          5
7       G    6.0          2          4
8       H    7.0          2          4
9       I    6.5          2          4
10      J    7.0          2          2
11      K    7.0          2          4
1
Aramis7d 21 avril 2017 à 04:48

Je pense que vous avez déjà tout ce dont vous avez besoin dans la réponse de @ griffmer. Mais une manière moins élégante mais peut-être plus intuitive pourrait être une boucle:

## Your data:
df <- data.frame(
        Game = LETTERS[1:11],
        Rating = c(6,7,6.5,7,7,9.5,6,7,6.5,7,7),
        MinPlayers = c(rep(3,5), rep(2,6)),
        MaxPlayers = c(6,7,NA,6,5,5,4,4,NA,2,4)     
)

## Loop over rows:
df$MaxPlayersGuess <- vapply(1:nrow(df), function(ii){
            if (is.na(df$MaxPlayers[ii])){
                median(df$MaxPlayers[df$MinPlayers == df$MinPlayers[ii]],
                        na.rm = TRUE)               
            } else {
                df$MaxPlayers[ii]
            }           
        }, numeric(1))

Ce qui vous donne

df
#    Game Rating MinPlayers MaxPlayers MaxPlayersGuess
# 1     A    6.0          3          6               6
# 2     B    7.0          3          7               7
# 3     C    6.5          3         NA               6
# 4     D    7.0          3          6               6
# 5     E    7.0          3          5               5
# 6     F    9.5          2          5               5
# 7     G    6.0          2          4               4
# 8     H    7.0          2          4               4
# 9     I    6.5          2         NA               4
# 10    J    7.0          2          2               2
# 11    K    7.0          2          4               4
1
ikop 21 avril 2017 à 04:39