2017-03-05 7 views
1

Ich habe tägliche Rücklieferungsdaten für mehrere Unternehmen und müssen diese Werte entfernen, die eine bestimmte Beziehung zum vorherigen (= der Vortag) Rückgabewert haben. In einer mathematischen Formel sieht es in etwa so aus: (1 + r) * (1 + e) ​​-1 < = 50%, wobei r die Rendite des aktuellen Tages ist und e die Rendite des Vortages und mindestens entweder r oder e, die größer als 100% sind. Der Datenrahmen DF sieht so aus.Entfernen Sie Werte basierend auf bestimmten Beziehung zum vorherigen Wert in derselben Spalte

Date   A  B  C  D 
01.01.2015 0.15 0.17 0.70 0.65 
02.01.2015 1.01 0.75 0.01 -0.18 
01.02.2015 -0.50 0.64 1.20 0.1 
06.02.2015 0.12 0.54 0.13 1.50 
01.03.2016 0.45 0.54 1.89 0.56 

Nach Anwendung dieses Filters sollte DF so aussehen.

Date   A  B  C  D 
01.01.2015 0.15 0.17 0.70 0.65 
02.01.2015 1.01 0.75 0.01 -0.18 
01.02.2015 NA 0.64 1.20 0.1 
06.02.2015 0.12 0.54 0.13 1.50 
01.03.2016 0.45 0.54 1.89 0.56 

Vielen Dank für Ihre Hilfe!

+0

Können Sie erklären, wie Sie von der Eingabe zum Ausgang gekommen sind. Der einzige Unterschied, den ich erkenne, ist um 1.2.2015/A. Und was ist der Unterschied zu 1.2.2015/B. –

+0

1.2.2015 A: (1 + (- 0,5) * (1 + 1,01) -1 = 0,005 ergo <50% (0,5) und e in diesem Fall ist größer als 100% (1,0) 1.2.2015 B: Ich sehe keinen Fall, wo dies getan werden muss – Henky

Antwort

1

Ich würde versuchen, diese:

library(tidyverse) 

check_fn <- function(Z){ 
    ifelse(((lag(Z, n=1) > 1 | Z >1) & ((1+lag(Z, n=1))*(1+Z) <= 1.5)), NA, Z) 
} 

Y <- X %>% 
    mutate_at(vars(2:5), check_fn) 

Y[1, 2:5] <- X[1, 2:5] 

Y 

..., die erzeugt:

 Date A B C  D 
1 01.01.2015 0.15 0.17 0.70 0.65 
2 02.01.2015 1.01 0.75 0.01 -0.18 
3 01.02.2015 NA 0.64 1.20 0.10 
4 06.02.2015 0.12 0.54 0.13 1.50 
5 01.03.2016 0.45 0.54 1.89 0.56 

Ich hoffe, dass es Ihnen hilft.

0

Entschuldigung, ich habe etwas von Ihrem Beitrag falsch gelesen. Ich habe es so korrigiert, dass es Ihrer erwarteten Ausgabe entspricht.

library(data.table) 
setDT(dat) 
dat = dat[ , lapply(.SD, relationship), .SDcols = c("A", "B", "C", "D")] 

relationship = function(x){ 
    return(ifelse(((1 + x)*(1 + shift(x)) - 1) < .5 & !is.na(shift(x)) & (x > 1 | shift(x) > 1), NA, x)) 
} 

> dat[ , lapply(.SD, relationship), .SDcols = c("A", "B", "C", "D")] 
     A B C  D 
1: 0.15 0.17 0.70 0.65 
2: 1.01 0.75 0.01 -0.18 
3: NA 0.64 1.20 0.10 
4: 0.12 0.54 0.13 1.50 
5: 0.45 0.54 1.89 0.56 

können Sie die Daten cbind zurück auf die data.table

sollte ich hinzufügen einhüllen gibt es viele weitere Spalten, die dies auf getan werden muss, und Sie wollen nicht, dass Sie sie alle heraus schreiben könnte so etwas tun.

Dates = dat$Date 
dat[ , "Date" := NULL] 
dat = dat[ , lapply(.SD, relationship)] 

Das wird die Funktion auf jede Spalte in der data.table anwenden.

+0

R gibt mir einen Fehler, dass es kann in der Beziehungsfunktion keinen "Test" finden. – Henky

+0

@Henky Ich habe den Code korrigiert. Es sollte jetzt funktionieren. – Kristofersen

0

Möglicherweise gibt es eine elegangere Lösung.

> M=matrix(c(0.15,0.17,0.70,0.65,1.01,0.75,0.01,-0.18,-0.50,0.64,1.20,0.1,0.12,0.54,0.13,1.50,0.45,0.54,1.89,0.56),nrow = 5, byrow = TRUE) 
> M 
     [,1] [,2] [,3] [,4] 
[1,] 0.15 0.17 0.70 0.65 
[2,] 1.01 0.75 0.01 -0.18 
[3,] -0.50 0.64 1.20 0.10 
[4,] 0.12 0.54 0.13 1.50 
[5,] 0.45 0.54 1.89 0.56 
> ifelse(rbind(c(T,T,T,T), !(((M[2:5,]>1)|(M[1:4,]>1))&(((1+M[2:5,])*(1+M[1:4,])-1)<.5))), M, NA) 
    [,1] [,2] [,3] [,4] 
[1,] 0.15 0.17 0.70 0.65 
[2,] 1.01 0.75 0.01 -0.18 
[3,] NA 0.64 1.20 0.10 
[4,] 0.12 0.54 0.13 1.50 
[5,] 0.45 0.54 1.89 0.56 
Verwandte Themen