2017-10-11 1 views
3

Ich komme von Stata zu R und habe eine einfache Syntaxfrage, die ich nicht lösen konnte. Ich versuche, mehrere Währungen (GBP EUR JPY) zu durchlaufen, um eine Wechselkursanpassung vorzunehmen. Legen Sie für jeden Datensatz, der auf eine der oben aufgeführten Währungen lautet, "amount_usd" gleich "betrag" dividiert durch den Wechselkurs (USDGBP, USDEUR, USDJPY) fest.Syntax von for-Schleifen in R

Daten erstellen:

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 

ich verschiedene Versionen der for-Schleife unten, aber ohne Erfolg versucht. Ich würde gerne Hinweise auf (1) richtige Loop-Syntax und (2) Tipps, um den Code eleganter zu machen.

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 { 
    } 
} 

Die resultierende df $ amount_usd sollte sich auf die Werte annehmen:

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

Bitte können Sie das Ergebnis von 'dput (head (df)) einfügen' – dww

+1

Ein reproduzierbares Beispiel und eine gewünschte Ausgabe wäre nützlich. – Cris

+0

Erwartete Ausgabe wird ebenfalls benötigt – dww

Antwort

4

Was Sie wirklich wollen, sind vektorisiert Operationen statt Schleifen. Die Idee besteht darin, den Teil der Daten, den Sie ändern möchten, mit der Zeilenindexierung zu unterteilen und dann die gesamte Datenverarbeitung gleichzeitig auszuführen.

Zunächst müssen Sie Spalten nicht numerisch referenzieren. Statt

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

können Sie nur verwenden

df[, "currency"] 

oder es ist alias mit dem $ Operator

df$currency 

Sie einen Vektor verwenden können, um festzustellen, welche Zeilen Ihres Datenrahmen ein bestimmtes Match Wert

gbp_rows <- df$currency == "GBP" 

und Sie können nur die Zeilen, so etwas wie

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

zu dass auf neue Werte zuweisen verwenden Obwohl ich glaube, dass muss fxGBP eine Konstante ist, richtig? Vielleicht wird so etwas funktionieren?

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

Wie kommentiert wurde, eine reproduzierbare Version Ihres Problems wäre hilfreich, ich bin nicht sicher, ob dies ist, was Sie zu tun versuchen.

EDIT: Eine Kombination von dem, was ich sagte, und Cris Antwort jetzt, dass wir ein 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

Dank Brian, die Lösung funktionierte gut für eine Währung. Meine größere Sorge ist, dass ich dieselben Befehle für alle Währungen ausführen möchte. Wenn ich "gbp_rows" Vektoren für mehrere Währungen erzeugen möchte, wäre die Stata Syntax etwas wie: "foreach curr in gbp eur jpy {gen' curr'_gbp = (currency == "' curr '")}". Wie würde ich das geloopte Element in der R-Syntax ähnlich referenzieren? –

3

diese Daten verwenden:

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)) 

Sie tun können:

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

Was produzieren diese Ergebnisse:

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 

So gibt Ihnen die Wechselkursanpassung für alle Ihre Währungen. Hoffe es hilft.

+0

Ah, sehr elegant! Gibt es eine einfache Möglichkeit, die resultierende Ausgabe in einer Variablen anstatt einzeln für jede Währung zu kombinieren? –

+1

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

+0

Diese Methode endet jedes Mal neu überschreiben df $ Menge_usd. Gibt es eine Alternative? –