2015-01-08 15 views
6

Sto sviluppando un modello che prevede una fertilità completa per una coorte di età. Al momento ho una cornice dati come questa, dove le righe sono invecchiate e le colonne sono anni. Il valore in ogni cella è la fertilità età-specifica per quell'anno:In R, convertire le diagonali dei frame di dati in righe

> df1 
    iso3 sex age fert1953 fert1954 fert1955 
14 AUS female 13 0.000 0.00000 0.00000 
15 AUS female 14 0.000 0.00000 0.00000 
16 AUS female 15 13.108 13.42733 13.74667 
17 AUS female 16 26.216 26.85467 27.49333 
18 AUS female 17 39.324 40.28200 41.24000 

Tuttavia, quello che voglio è ogni riga di essere una coorte. Poiché le righe e le colonne rappresentano singoli anni, i dati di coorte possono essere ottenuti ottenendo la diagonale. Sto cercando un risultato come questo:

> df2 
    iso3 sex ageIn1953 fert1953 fert1954 fert1955 
14 AUS female  13 0.000 0.00000 13.74667 
15 AUS female  14 0.000 13.42733 27.49333 
16 AUS female  15 13.108 26.85467 41.24000 
17 AUS female  16 26.216 40.28200 [data..] 
18 AUS female  17 39.324 [data..] [data..] 

Ecco il frame di dati df1:

df1 <- structure(list(iso3 = c("AUS", "AUS", "AUS", "AUS", "AUS"), sex = c("female", 
"female", "female", "female", "female"), age = c(13, 14, 15, 
16, 17), fert1953 = c(0, 0, 13.108, 26.216, 39.324), fert1954 = c(0, 
0, 13.4273333333333, 26.8546666666667, 40.282), fert1955 = c(0, 
0, 13.7466666666667, 27.4933333333333, 41.24)), .Names = c("iso3", 
"sex", "age", "fert1953", "fert1954", "fert1955"), class = "data.frame", row.names = 14:18) 

EDIT:

Ecco la soluzione che ho usato alla fine. Si basa sulla risposta di David, ma dovevo farlo per ogni livello di iso3.

df.ls <- lapply(split(f3, f = f3$iso3), FUN = function(df1) { 
    n <- ncol(df1) - 4 
    temp <- mapply(function(x, y) lead(x, n = y), df1[, -seq_len(4)], seq_len(n)) 
    return(cbind(df1[seq_len(4)], temp)) 
}) 
f4 <- do.call("rbind", df.ls) 
+0

Vuoi solo ad essere in ritardo voi set di dati? –

+0

Sì, ma penso che sarebbe molto complicato. Lo sto facendo per 188 paesi da oltre 50 anni. Se riesci a pensare a un buon modo per farlo, potrebbe essere una buona soluzione. – rsoren

risposta

4

non ho ancora testato per la velocità, ma data.tablev1.9.5, ha recentemente implementato un nuovo (scritto in C) Funzione di anticipo/ritardo chiamato shift

Così per le colonne che si desidera spostare, si potrebbe potenzialmente utilizzarlo in combinazione con mapply, ad esempio

library(data.table) 
n <- ncol(df1) - 4 # the number of years - 1 
temp <- mapply(function(x, y) shift(x, n = y, type = "lead"), df1[, -seq_len(4)], seq_len(n)) 
cbind(df1[seq_len(4)], temp) # combining back with the unchanged columns 
# iso3 sex age fert1953 fert1954 fert1955 
# 14 AUS female 13 0.000 0.00000 13.74667 
# 15 AUS female 14 0.000 13.42733 27.49333 
# 16 AUS female 15 13.108 26.85467 41.24000 
# 17 AUS female 16 26.216 40.28200  NA 
# 18 AUS female 17 39.324  NA  NA 

Edit: si può facilmente installare lo sviluppo versione di data.table da GitHub utilizzando

library(devtools) 
install_github("Rdatatable/data.table", build_vignettes = FALSE) 

In entrambi i casi, se si vuole dplyr, qui va

library(dplyr) 
n <- ncol(df1) - 4 # the number of years - 1 
temp <- mapply(function(x, y) lead(x, n = y), df1[, -seq_len(4)], seq_len(n)) 
cbind(df1[seq_len(4)], temp) 
# iso3 sex age fert1953 fert1954 fert1955 
# 14 AUS female 13 0.000 0.00000 13.74667 
# 15 AUS female 14 0.000 13.42733 27.49333 
# 16 AUS female 15 13.108 26.85467 41.24000 
# 17 AUS female 16 26.216 40.28200  NA 
# 18 AUS female 17 39.324  NA  NA 
+0

Sembra fantastico. Sfortunatamente la v1.9.4 è l'ultima versione di data.table su CRAN, e ho problemi a scaricare la versione di sviluppo di GitHub. Apparentemente questo è un problema comune su Windows. Sto lavorando per usare invece la funzione '' 'lead()' '' di dplyr; Penso che dovrebbe funzionare ... – rsoren

+0

Vedere la mia modifica quindi –

+0

Ho fatto un aggiustamento per tenere conto del fatto che questo deve essere fatto separatamente per ogni valore di '' 'iso3''' (vedi la mia modifica sopra). Il problema con data.table era che ricevevo un errore "Command failed (1)", che rendeva più difficile il solito '' 'install_github()' ''. C'è un link su questo nella pagina di installazione di data.table. Grazie mille! – rsoren

1

Ecco un approccio di base R:

df1[,5:ncol(df1)] <- mapply(function(x, y) {vec.list <- df1[-1:-y, x] 
         length(vec.list) <- nrow(df1) 
         vec.list}, 
         x=5:ncol(df1), y=1:(ncol(df1)-4)) 
df1 
# iso3 sex age fert1953 fert1954 fert1955 
#14 AUS female 13 0.000 0.00000 13.74667 
#15 AUS female 14 0.000 13.42733 27.49333 
#16 AUS female 15 13.108 26.85467 41.24000 
#17 AUS female 16 26.216 40.28200  NA 
#18 AUS female 17 39.324  NA  NA 
Problemi correlati