2017-10-11 3 views
3

Je viens de R Stata et j'ai une question de syntaxe simple que je n'ai pas été capable de résoudre. J'essaie de boucler plusieurs devises (GBP EUR JPY) pour effectuer un ajustement du taux de change. Pour chaque enregistrement libellé dans l'une des devises énumérées ci-dessus, définissez "amount_usd" égal à "amount" divisé par le taux de change (USDGBP, USDEUR, USDJPY).Syntaxe des boucles for dans R

Créer des données:

df <- data.frame(currency = c("GBP", "GBP", "EUR", "EUR", "JPY"), 
       amount = c(100, 200, 100, 200, 100), 
       USDGBP = c(1.5, 1.5, 1.5, 1.5, 1.5), 
       USDEUR = c(1.1, 1.1, 1.1, 1.1, 1.1), 
       USDJPY = c(100, 100, 100, 100, 100)) 

df$amount_usd <- df$amount 

J'ai essayé différentes versions de la boucle ci-dessous, mais sans chance. J'apprécierais des pointeurs sur (1) la syntaxe de boucle appropriée, et (2) des conseils pour rendre le code plus élégant.

df$face_value_curr_usd <- df$face_value_curr 

for (curr in c("GBP", "EUR", "JPY")) { 
    if (df[,which(colnames(df) == "currency")] == curr) { 
     df[,which(colnames(df) == "amount_usd")] <- 
      df[, which(colnames(df) == "amount")]/df[,which(colnames(df) == c("USD",curr))] 
    } 
    else { 
    } 
} 

La résultante df amount_usd de $ devrait prendre les valeurs:

c(66.67, 133.33, 90.91, 181.82, 1) 
+1

S'il vous plaît pourriez-vous coller dans le résultat de 'dput (head (df))' – dww

+1

Un exemple reproductible et une sortie désirée serait utile. – Cris

+0

Sortie attendue également nécessaire – dww

Répondre

4

Qu'est-ce que vous voulez vraiment sont opérations vectorisés au lieu de boucles. L'idée est de sous-traiter la partie des données que vous voulez modifier en utilisant l'indexation des lignes, puis de faire tout le calcul en même temps. Tout d'abord, vous n'avez pas besoin de référencer les colonnes numériquement. Au lieu de

df[,which(colnames(df) == "currency")] 

vous pouvez simplement utiliser

df[, "currency"] 

ou il est alias avec l'opérateur $

df$currency 

Vous pouvez utiliser un vecteur pour identifier les lignes de votre trame de données correspondent à une donnée valeur

gbp_rows <- df$currency == "GBP" 

et vous pouvez utiliser que pour affecter de nouvelles valeurs aux seules lignes, quelque chose comme

df$face_value_curr_usd[gbp_rows] <- df$amount[gbp_rows]/df$fxGBP[gbp_rows] 

Même si je dois penser que fxGBP est une constante, correcte? Alors peut-être que quelque chose comme ça va faire? Comme cela a été commenté

df$face_value_curr_usd[gbp_rows] <- df$amount[gbp_rows]/fxGBP 

, une version reproductible de votre problème serait utile, je ne sais pas si c'est ce que vous essayez de faire.

EDIT: Une combinaison de ce que je disais et la réponse de Cris maintenant que nous avons un df:

df <- data.frame(currency = c("GBP", "GBP", "EUR", "EUR", "JPY"), 
       amount = c(100, 200, 100, 200, 100), 
       USDGBP = c(1.5, 1.5, 1.5, 1.5, 1.5), 
       USDEUR = c(1.1, 1.1, 1.1, 1.1, 1.1), 
       USDJPY = c(100, 100, 100, 100, 100)) 

for(curr in unique(df$currency)) { 
    this_curr_rows <- df$currency == curr 
    df$amount_usd[this_curr_rows] <- df$amount[this_curr_rows]/df[this_curr_rows, paste0("USD", curr)] 
} 
+1

Merci Brian, la solution a bien fonctionné pour une devise. Ma plus grande préoccupation est que je veux exécuter le même ensemble de commandes pour toutes les devises. Si je voulais générer des vecteurs "gbp_rows" pour plusieurs devises, la syntaxe Stata serait semblable à: "foreach curr in gbp eur jpy {gen' curr'_gbp = (devise == "' curr '")}". Comment puis-je référencer de manière similaire l'élément en boucle dans la syntaxe R? –

3

En utilisant ces données:

df <- data.frame(currency = c("GBP", "GBP", "EUR", "EUR", "JPY"), 
       amount = c(100, 200, 100, 200, 100), 
       USDGBP = c(1.5, 1.5, 1.5, 1.5, 1.5), 
       USDEUR = c(1.1, 1.1, 1.1, 1.1, 1.1), 
       USDJPY = c(100, 100, 100, 100, 100)) 

Vous pouvez faire:

for(curr in unique(df$currency)){ 
    df[paste("amount_usd",curr,sep="-")]=df$amount/df[paste("USD",curr, sep="")] 
} 

Qui produisent ce résultat:

currency amount USDGBP USDEUR USDJPY amount_usd-GBP amount_usd-EUR amount_usd-JPY 
GBP 100 1.5 1.1 100 66.7 90.9 1 
GBP 200 1.5 1.1 100 133.3 181.8 2 
EUR 100 1.5 1.1 100 66.7 90.9 1 
EUR 200 1.5 1.1 100 133.3 181.8 2 
JPY 100 1.5 1.1 100 66.7 90.9 1 

Ainsi, il vous donne l'ajustement du taux de change pour toutes vos devises. J'espère que ça aide.

+0

Ah, très élégant! Existe-t-il un moyen simple de combiner la sortie résultante dans une variable plutôt que individuellement pour chaque devise? –

+1

'df $ amount_usd <- df $ montant/df [paste0 (" USD ", curr)]' –

+0

Cette méthode finit par réécrire df $ amount_usd chaque fois. Y a-t-il une alternative? –