2017-02-28 2 views
0

J'essaie de faire quelque chose de très simple dans R mais je ne peux pas le faire correctement.générer et remplacer proprement des valeurs basées sur une condition

Prenons l'ensemble de données « diamants » de ggplot 2

glimpse(diamonds) 

$ carat <dbl> 0.23, 0.21, 0.23, 0.29, 0.31, 0.24, 0.24, 0.26, 0.22, 0.23, 0.30, 0.23, 0.22, 0.31, 0.20, 0.32, 0.30, 0.30, 0.30, 0.30, 0.30, 0.23, 0.23, 0.31, 0.31, 0.23, ... 
$ cut  <ord> Ideal, Premium, Good, Premium, Good, Very Good, Very Good, Very Good, Fair, Very Good, Good, Ideal, Premium, Ideal, Premium, Premium, Ideal, Good, Good, Ver... 
$ color <ord> E, E, E, I, J, J, I, H, E, H, J, J, F, J, E, E, I, J, J, J, I, E, H, J, J, G, I, J, D, F, F, F, E, E, D, F, E, H, D, I, I, J, D, D, H, F, H, H, E, H, F, G, ... 
$ clarity <ord> SI2, SI1, VS1, VS2, SI2, VVS2, VVS1, SI1, VS2, VS1, SI1, VS1, SI1, SI2, SI2, I1, SI2, SI1, SI1, SI1, SI2, VS2, VS1, SI1, SI1, VVS2, VS1, VS2, VS2, VS1, VS1,... 
$ depth <dbl> 61.5, 59.8, 56.9, 62.4, 63.3, 62.8, 62.3, 61.9, 65.1, 59.4, 64.0, 62.8, 60.4, 62.2, 60.2, 60.9, 62.0, 63.4, 63.8, 62.7, 63.3, 63.8, 61.0, 59.4, 58.1, 60.4, ... 
$ table <dbl> 55, 61, 65, 58, 58, 57, 57, 55, 61, 61, 55, 56, 61, 54, 62, 58, 54, 54, 56, 59, 56, 55, 57, 62, 62, 58, 57, 57, 61, 57, 57, 57, 59, 58, 58, 59, 59, 54, 59, ... 
$ price <int> 326, 326, 327, 334, 335, 336, 336, 337, 337, 338, 339, 340, 342, 344, 345, 345, 348, 351, 351, 351, 351, 352, 353, 353, 353, 354, 355, 357, 357, 357, 402, 4... 
$ x  <dbl> 3.95, 3.89, 4.05, 4.20, 4.34, 3.94, 3.95, 4.07, 3.87, 4.00, 4.25, 3.93, 3.88, 4.35, 3.79, 4.38, 4.31, 4.23, 4.23, 4.21, 4.26, 3.85, 3.94, 4.39, 4.44, 3.97, ... 
$ y  <dbl> 3.98, 3.84, 4.07, 4.23, 4.35, 3.96, 3.98, 4.11, 3.78, 4.05, 4.28, 3.90, 3.84, 4.37, 3.75, 4.42, 4.34, 4.29, 4.26, 4.27, 4.30, 3.92, 3.96, 4.43, 4.47, 4.01, ... 
$ z  <dbl> 2.43, 2.31, 2.31, 2.63, 2.75, 2.48, 2.47, 2.53, 2.49, 2.39, 2.73, 2.46, 2.33, 2.71, 2.27, 2.68, 2.68, 2.70, 2.71, 2.66, 2.71, 2.48, 2.41, 2.62, 2.59, 2.41, ... 

que nous voulons calculer un nouveau prix qui inclurait une réduction de 10% sur les diamants « juste ». Ce que je voudrais réaliser dans R serait dans Stata:

generate price_cut = . 
replace price_cut = price if cut != "Fair" 
replace price_cut = (0.90 * price) if cut =="Fair" 

Mais je ne peux pas y arriver. J'ai essayé

diamonds["price_cut"] <- 0 
    diamonds[diamonds$cut == "Ideal", "price_cut"] <- diamonds$price 
    Error in `[<-.data.frame`(`*tmp*`, diamonds$cut == "Ideal", "price_cut", : 
     replacement has 53940 rows, data has 21551 

J'ai essayé aussi

diamonds["price_cut"] <- 0 
diamonds[diamonds$cut == "Ideal", "price_cut"] <- diamonds$price 
Error in `[<-.data.frame`(`*tmp*`, diamonds$cut == "Ideal", "price_cut", : 
    replacement has 53940 rows, data has 21551 
diamonds$price_cut[diamonds$cut !="Ideal"] <- diamonds$price * 0.9 
Warning message: 
In diamonds$price_cut[diamonds$cut != "Ideal"] <- diamonds$price : 
    number of items to replace is not a multiple of replacement length 

Et il fonctionne un peu dans mon exemple de jouet, mais pas dans un ensemble de données plus complexes avec des valeurs manquantes et ainsi de suite.

Qu'est-ce que je fais mal?

+0

vous n'êtes pas sous-ensembles de la partie droite: 'diamants [diamants coupé $ == "Idéal"," price_cut "] <- diamonds $ price [diamants $ cut ==" Idéal "]' – Cath

+0

'require (dplyr)'; 'diamonds%>% mute (cut = comme.character (cut), new_price = ifelse (cut ==" Juste ", prix * 0.9, prix))' – count

+1

FWIW, le code Stata peut être coupé de 3 lignes à 1: 'générer price_cut = cond (couper ==" Juste ", 0.90 * prix, prix)' –

Répondre

2

une traduction directe de votre code Stata serait

diamonds$price_cut <- NA 
diamonds$price_cut[diamonds$cut != "Fair"] <- diamonds$price[diamonds$cut != "Fair"] 
diamonds$price_cut[diamonds$cut == "Fair"] <- (0.90 * diamonds$price[diamonds$cut == "Fair"]) 

Ceci peut être réalisé en une ligne en utilisant des arguments vectorisés comme

diamonds$price_cut <- c(1, .9)[(diamonds$cut == "Fair") + 1] * diamonds$price 

ou, en utilisant plus communément ifelse:

diamonds$price_cut <- ifelse(diamonds$cut == "Fair", diamonds$price, 0.9 * diamonds$price) 

Side note: un Stata one-liner dans le même esprit

generate price_cut = price - ((cut == "Fair") * 0.1) 

En R

diamonds$price_cut <- diamonds$price - ((diamonds$cut == "Fair") * 0.1) 
+0

Merci beaucoup pour votre aide! –