2016-08-04 11 views
3

Ich habe eine Datentabelle wie dieseErstellen einer neuen Spalte durch Subtrahieren von Werten basierend auf einem Schlüssel in R?

ID  DAYS FREQUENCY 
"ads" 20  3 
"jwa" 45  2 
"mno" 4  1 
"ads" 13  3 
"jwa" 60  2 
"ads" 18  3 

ich eine Spalte hinzufügen möchten, dass die Tage auf der Grundlage der ID subtrahiert und die nächsten Tage zusammen subtrahieren. Meine neue Tabelle würde so mag:

ID  DAYS FREQUENCY DAYS DIFF 
"ads" 20  3   2 (because 20-18) 
"jwa" 45  2   NA (because no value greater than 45 for that id) 
"mno" 4  1   NA 
"ads" 13  3   NA 
"jwa" 60  2   15 
"ads" 18  3   5 

Bonus: Gibt es eine Möglichkeit, die Merge-Funktion zu benutzen?

+0

Warum würden Sie/erwarten wollen Verwenden Sie eine Zusammenführung hier? Fwiw, wenn Sie ein Paket installieren möchten, kann dies mit 'library (data.table); setDT (DF) [order (TAGE), dd: = DAYS - shift (TAGE), by = ID] ' – Frank

Antwort

1

Hier ist eine Antwort mit dplyr:

require(dplyr) 
mydata %>% 
    mutate(row.order = row_number()) %>% # row numbers added to preserve original row order 
    group_by(ID) %>% 
    arrange(DAYS) %>% 
    mutate(lag = lag(DAYS)) %>% 
    mutate(days.diff = DAYS - lag) %>% 
    ungroup() %>% 
    arrange(row.order) %>% 
    select(ID, DAYS, FREQUENCY, days.diff) 

Ausgang:

 ID DAYS FREQUENCY days.diff 
    <fctr> <int>  <int>  <int> 
1 ads 20   3   2 
2 jwa 45   2  NA 
3 mno  4   1  NA 
4 ads 13   3  NA 
5 jwa 60   2  15 
6 ads 18   3   5 
+0

Sie müssen nicht zwei muate-Aufrufe hintereinander machen. 'mutate (x = g (z), y = f (x))' ist eine machbare Sache. – Frank

+1

Dank @Frank, lernte etwas Neues! –

0

Sie können diese mit dplyr tun und eine schnelle Schleife:

library(dplyr) 

# Rowwise data.frame creation because I'm too lazy not to copy-paste the example data 
df <- tibble::frame_data(
    ~ID, ~DAYS, ~FREQUENCY, 
    "ads", 20,  3, 
    "jwa", 45,  2, 
    "mno", 4,  1, 
    "ads", 13,  3, 
    "jwa", 60,  2, 
    "ads", 18,  3 
) 

# Subtract each number in a numeric vector with the one following it 
rolling_subtraction <- function(x) { 
    out <- vector('numeric', length(x)) 
    for (i in seq_along(out)) { 
    out[[i]] <- x[i] - x[i + 1] # x[i + 1] is NA if the index is out of bounds 
    } 

    out 
} 

# Arrange data.frame in order of ID/Days and apply rolling subtraction 
df %>% 
    arrange(ID, desc(DAYS)) %>% 
    group_by(ID) %>% 
    mutate(days_diff = rolling_subtraction(DAYS)) 
Verwandte Themen