2016-05-22 4 views
1

Für eine Probe Datenrahmen ist:Spalte hinzufügen Detaillierung aus, die Jahresdaten

df <- structure(list(region = structure(1:8, .Label = c("a", "b", "c", 
"d", "e", "f", "g", "h"), class = "factor"), y.2012 = c(5.5, 
NA, 4.7, 3.6, NA, NA, 4.6, NA), y.2013 = c(5.7, NA, NA, 3.8, 
NA, 6.2, NA, NA), y.2014 = c(NA, 6.3, NA, 4.1, 5.1, NA, NA, NA 
)), .Names = c("region", "y.2012", "y.2013", "y.2014"), class = "data.frame", row.names = c(NA, 
-8L)) 

Ich möchte eine zusätzliche Spalte hinzufügen, die den Wert der letzten Spalte aufzeichnet. Ich habe dies bisher (from this question):

df$variable <- apply(df[-1], 1, function(x) { 
    i1 <- tail(x[!is.na(x)],1) 
    if(length(i1)>0) i1 else NA}) 
df$variable 

Darüber hinaus habe ich (als eine andere Spalte) hinzufügen möchten, das Jahr der ‚variable‘ Daten aus ist.

Kann mir jemand dabei helfen?

+0

Nun, hinzufügen, um Ihre Funktion, wenn Sie 'Namen hinzufügen (Wenn (Länge (i1 ...)))), erhalten Sie eine Liste mit den Spaltennamen, aus denen jeder Wert stammt. – Sotos

+2

Sie sollten auf jeden Fall versuchen, Ihre Daten von Weitem zu Lang umzuformen, wobei Sie zuerst eine Aufzeichnung pro Region x Jahr gültige Beobachtung haben –

Antwort

4

Sie könnten das erreichen mit:

df1$variable <- apply(df1[,-1], 1, function(x) names(x)[!is.na(x)][sum(!is.na(x))]) 

die gibt:

> df1 
    region y.2012 y.2013 y.2014 variable 
1  a 5.5 5.7  NA y.2013 
2  b  NA  NA 6.3 y.2014 
3  c 4.7  NA  NA y.2012 
4  d 3.6 3.8 4.1 y.2014 
5  e  NA  NA 5.1 y.2014 
6  f  NA 6.2  NA y.2013 
7  g 4.6  NA  NA y.2012 
8  h  NA  NA  NA   

Sie können die leeren Zellen ersetzen mit:

df1[df1$variable=='character(0)','variable'] <- NA 

die gibt:

> df1 
    region y.2012 y.2013 y.2014 variable 
1  a 5.5 5.7  NA y.2013 
2  b  NA  NA 6.3 y.2014 
3  c 4.7  NA  NA y.2012 
4  d 3.6 3.8 4.1 y.2014 
5  e  NA  NA 5.1 y.2014 
6  f  NA 6.2  NA y.2013 
7  g 4.6  NA  NA y.2012 
8  h  NA  NA  NA  NA 

Wie in den Kommentaren gesagt, ist es wahrscheinlich besser, zuerst Ihr langes Format umzugestalten und dann zu sehen, welches Jahr den letzten Wert hat.Mit Hilfe der data.table Paket:

library(data.table) 
df2 <- melt(setDT(df1), id.vars='region', variable.name = 'year') 
df2[, year := as.integer(gsub('^y.','',year)) 
    ][, var := tail(year[!is.na(value)],1), by = region] 

die gibt:

> df2 
    region year value var 
1:  a 2012 5.5 2013 
2:  b 2012 NA 2014 
3:  c 2012 4.7 2012 
4:  d 2012 3.6 2014 
5:  e 2012 NA 2014 
6:  f 2012 NA 2013 
7:  g 2012 4.6 2012 
8:  h 2012 NA NA 
9:  a 2013 5.7 2013 
10:  b 2013 NA 2014 
11:  c 2013 NA 2012 
12:  d 2013 3.8 2014 
13:  e 2013 NA 2014 
14:  f 2013 6.2 2013 
15:  g 2013 NA 2012 
16:  h 2013 NA NA 
17:  a 2014 NA 2013 
18:  b 2014 6.3 2014 
19:  c 2014 NA 2012 
20:  d 2014 4.1 2014 
21:  e 2014 5.1 2014 
22:  f 2014 NA 2013 
23:  g 2014 NA 2012 
24:  h 2014 NA NA 

Eine ähnliche Lösung mit dplyr & tidyr:

library(dplyr) 
library(tidyr) 
df2 <- df1 %>% 
    gather(year, value, -1) %>% 
    mutate(year = as.integer(gsub('^y.','',year))) %>% 
    group_by(region) %>% 
    mutate(var = as.integer(ifelse(all(is.na(value)==TRUE), NA, tail(year[!is.na(value)],1)))) 
0

Sie könnten die Schmelzfunktion des reshape2-Pakets verwenden, um in ein langes Format zu konvertieren, und dann die stringr-Paketfunktion str_replace, um zu einem Jahr ohne "y" zu gelangen. Präfix. Siehe unten, zuerst konvertiert die zu langes Format:

library(reshape2) 
df2 <- reshape2::melt(df, 
         id.vars="region", 
         variable.name="yearStr") 
df2 

Ausgang:

region yearStr value 
1  a y.2012 5.5 
2  b y.2012 NA 
3  c y.2012 4.7 
4  d y.2012 3.6 
... 

Dann beheben, um das Jahr nach oben:

df2$year <- as.numeric(stringr::str_replace(df2$yearStr, "y.", "")) 

df2 

Ausgang:

region yearStr value year 
1  a y.2012 5.5 2012 
2  b y.2012 NA 2012 
3  c y.2012 4.7 2012 
4  d y.2012 3.6 2012 
... 

zu zu den letzten Jahreszeilen mit Jahresbezeichnung (mit dp lyr):

library(dplyr) 
regions <- group_by(df2, region) 
df3 <- filter(regions[!is.na(regions$value),], min_rank(desc(year)) <= 1) 
as.data.frame(df3) 

Ausgang:

region yearStr value year 
1  c y.2012 4.7 2012 
2  g y.2012 4.6 2012 
3  a y.2013 5.7 2013 
4  f y.2013 6.2 2013 
5  b y.2014 6.3 2014 
6  d y.2014 4.1 2014 
7  e y.2014 5.1 2014 

Sicherlich weniger prägnant als @Procrastinatus Maximus, aber die Zwischenergebnisse könnten einige Vorteile für das Plotten oder andere Analyse haben.

ÜBERARBEITET: dplyr hinzugefügt, um nur die letzten Datenzeilen für jede Region anzuzeigen.

Verwandte Themen