2017-12-02 1 views
2

enter image description hereSaison Boxdiagramm in R oder Matlab

DATE  obs1  obs2 obs3  
1981-01-01 2032.409 3142.46 1741.143 
1981-01-02 2023.687 3870.04 1735.256 
1981-01-03 2014.274 4126.25 1728.556 
1981-01-04 2005.795 2615.91 1722.985 
1981-01-05 2000.674 2940.83 1722.317 
1981-01-06 1998.477 3258.69 1723.937 
1981-01-07 1997.014 3371.6 1724.104 
1981-01-08 1995.576 3184.13 1722.624 
1981-01-09 1993.706 3540.76 1719.592 
1981-01-10 1991.286 3312.43 1715.156 
1981-01-11 1988.633 3028.65 1710.141 
1981-01-12 1986.147 3212.79 1705.183 
1981-01-13 1984.229 3193.23 1700.789 
1981-01-14 1982.756 3294.52 1697.785 
1981-01-15 1981.548 3553.78 1696.068 
1981-01-16 1980.561 3492.28 1694.544 
1981-01-17 1979.792 2452.09 1692.36 
1981-01-18 1979.224 1873.82 1689.525 
1981-01-19 1978.845 3218.28 1686.452 

Ich brauche saisonal plotten (Winter, Frühling, Sommer und Herbst) Box-Plot in R für die täglichen Daten wie oben gezeigt. Ich habe 10 Jahre Daten im obigen Format für verschiedene Stationen. Die Handlung sollte in einer Zahl sein, mit mehreren Boxplots in jeder Jahreszeit.

Antwort

2

Eine Lösung mit tidyverse und lubridate. tidyverse enthält dplyr und tidyr zum Durchführen von Datenkonflikten und ggplot2 zum Erstellen des Diagramms. lubridate soll die Daten im Datenrahmen behandeln.

Da der von Ihnen zur Verfügung gestellte Datensatz nicht sehr nützlich ist, da er nur einige wenige Datensätze erst ab Januar enthält, ist es unmöglich, einen Boxplot zu erstellen, der den saisonalen Unterschied zeigt. Die Struktur meines Beispieldatenrahmens ähnelt Ihrer Datenmenge, die Ihnen einige Hinweise als Ausgangspunkt für Ihr Problem in der realen Welt geben sollte.

# Set the seed for reproducibility 
set.seed(123) 

library(tidyverse) 
library(lubridate) 

# Create example data frame 
dt <- data_frame(DATE = seq(ymd("1980-01-01"), ymd("1989-12-31"), by = 1)) %>% 
    mutate(obs1 = rnorm(nrow(.), mean = 0, sd = 1), 
     obs2 = rnorm(nrow(.), mean = 1, sd = 2), 
     obs3 = rnorm(nrow(.), mean = 2, sd = 3)) 

head(dt) 
# # A tibble: 6 x 4 
#   DATE  obs1  obs2  obs3 
#  <date>  <dbl>  <dbl>  <dbl> 
# 1 1980-01-01 -0.56047565 0.7874145 2.7827006 
# 2 1980-01-02 -0.23017749 0.1517417 8.5720252 
# 3 1980-01-03 1.55870831 0.7193725 1.3293478 
# 4 1980-01-04 0.07050839 0.5454177 0.3253155 
# 5 1980-01-05 0.12928774 1.41.1245771 
# 6 1980-01-06 1.71506499 -0.6491910 4.5034395 

tail(dt) 
# # A tibble: 6 x 4 
#   DATE  obs1  obs2  obs3 
#  <date>  <dbl>  <dbl>  <dbl> 
# 1 1989-12-26 -0.3629796 0.6750946 0.8586325 
# 2 1989-12-27 0.1102218 2.8572337 9.8541328 
# 3 1989-12-28 -0.2700741 1.7614026 1.9109596 
# 4 1989-12-29 0.6920973 0.5275611 -0.4756240 
# 5 1989-12-30 0.9282803 1.3811225 1.5222535 
# 6 1989-12-31 0.5931301 -1.6638739 4.1157087 

Der Beispieldatenrahmen enthält Datensätze für 10 Jahre mit 3 Beobachtungsgruppen. Die Werte von jeder Spalte sind in normaler Verteilung mit verschiedenen Mitteln und Standardabweichungen.

Der erste Schritt besteht darin, den Datenrahmen zu verarbeiten, indem der Datensatz vom Breitformat in das Langformat konvertiert und eine Spalte hinzugefügt wird, die die Saisoninformationen anzeigt.

dt2 <- dt %>% 
    # Convert data frame from lwide format to long format 
    gather(Observation, Value, -DATE) %>% 
    # Remove "obs" in the Observation column 
    mutate(Observation = str_replace(Observation, "obs", "")) %>% 
    # Convert the DATE column to date class 
    mutate(DATE = ymd(DATE)) %>% 
    # Create Month column 
    mutate(Month = month(DATE)) %>% 
    # Create Season column 
    mutate(Season = case_when(
    Month %in% c(12, 1, 2)  ~ "winter", 
    Month %in% c(3, 4, 5)  ~ "spring", 
    Month %in% c(6, 7, 8)  ~ "summer", 
    Month %in% c(9, 10, 11)  ~ "fall", 
    TRUE      ~ NA_character_ 
)) 

Danach können wir ggplot2 verwenden, um die boxplot zu erstellen. Beachten Sie, dass ich stat_summary verwenden, um jeder Gruppe eine rote Linie hinzuzufügen, um den Mittelwert darzustellen.

# Create a boxplot using ggplot2 
# Specify the aesthetics 
ggplot(dt2, aes(x = Season, y = Value, fill = Observation)) + 
    # Specify the geom to be boxplot 
    geom_boxplot() +     
    # Add a red line to the mean 
    stat_summary(aes(ymax = ..y.., ymin = ..y..), 
       fun.y = "mean", 
       geom = "errorbar",    # Use geom_errorbar to add line as mean 
       color = "red", 
       width = 0.7, 
       position = position_dodge(width = 0.75), # Add the line to each group 
       show.legend = FALSE) 

enter image description here

2

Ok ... Der erste Schritt ist, eine Funktion für den Aufbau, den die Jahreszeit, in der ein gegebenes Datum fällt, erfassen kann. Glücklicherweise habe ich schon vor langer Zeit entwickelt, dass auch Jahreszeiten in der südlichen Hemisphäre (die umgekehrt sind) behandelt werden können.

Die Funktion implementiert keine Plausibilitätsprüfung, da ich sie mit bereits bereinigten Datensätzen verwendet habe, aber es sollte nicht schwer für Sie sein, einige zu implementieren (es sei denn, Sie entschließen sich, Ihre Datensätze vor der Verwendung zu bereinigen). Es funktioniert vektorisiert, um die Rechenleistung in Matlab zu maximieren.

Hier ist es:

function season = GetSeason(date,southern_hemisphere) 

    if (nargin == 1) 
     southern_hemisphere = false; 
    end 

    [~,month,day] = datevec(date); 
    offset = month + (day/100); 

    winter = (offset < 3.21) | (offset >= 12.22); 
    spring = ~winter & (offset < 6.21); 
    summer = ~winter & ~spring & (offset < 9.23); 
    autumn = ~winter & ~spring & ~summer; 

    offset(spring) = 0; 
    offset(summer) = 1; 
    offset(autumn) = 2; 
    offset(winter) = 3; 

    if (southern_hemisphere) 
     offset = offset + 2; 
    end 

    season = mod(offset,4) + 1; 
end 

Nun ist der erste Schritt, in Ihrem Skript, ist Ihre Beobachtungen aus einer Datensatz-Datei zu extrahieren. Um eine voll funktionsfähige Demo für Sie zu erstellen, habe ich einen Excel Datensatz erstellt.Aber Sie könnten auch einen CSV Datensatz mit verwenden fast keine Änderungen im Code oder andere von Matlab behandelt Dateiformate:

% detect the dataset columns format 
opts = detectImportOptions('data.xlsx'); 

% impose a specific format for the dataset columns 
opts = setvartype(opts,{'datetime' 'double' 'double' 'double'}); 

% extract data in a table variable 
data = readtable('data.xlsx',opts); 

% sanitize the table variable removing the rows with missing or invalid values 
data = rmmissing(data); 

% sort the table variable rows by date (default first rows, default ascending) 
data = sortrows(data); 

Der zweite Test besteht für die Beobachtung der entsprechenden Saison in immer Daten:

seasons = GetSeason(data.Date); 

der dritte Schritt, vorausgesetzt, wir alle diesen Prozess nur für die erste Spalte von Beobachtungen durchführen Obs1 genannt:

spring_1 = data.Obs1(seasons == 1); 
summer_1 = data.Obs1(seasons == 2); 
autumn_1 = data.Obs1(seasons == 3); 
winter_1 = data.Obs1(seasons == 4); 

Der vierte und letzte Schritt besteht darin, einen Boxplot für jede Jahreszeit in einem einzigen Graphen zu zeichnen (die Gruppierungsvariable groups muss als Argument in die boxplot Funktion übergeben werden, um zu wissen, wie viele Felder sie zeichnen muss und welche Werte verwendet werden)):

groups = [ 
    ones(size(spring_1)); 
    2 * ones(size(summer_1)); 
    3 * ones(size(autumn_1)); 
    4 * ones(size(winter_1)); 
]; 

figure(); 
boxplot([spring_1; summer_1; autumn_1; winter_1],groups); 
set(gca,'XTickLabel',{'Spring' 'Summer' 'Autumn' 'Winter'}); 

Und hier ist das Ergebnis:

Result

UPDATE mit voller Arbeits CODE FÜR ALLE ERKLÄRUNGEN

opts = detectImportOptions('data.xlsx'); 
opts = setvartype(opts,{'datetime' 'double' 'double' 'double'}); 

data = readtable('data.xlsx',opts); 
data = rmmissing(data); 
data = sortrows(data); 

seasons = GetSeason(data.Date); 

spring_1 = data.Obs1(seasons == 1); 
summer_1 = data.Obs1(seasons == 2); 
autumn_1 = data.Obs1(seasons == 3); 
winter_1 = data.Obs1(seasons == 4); 
spring_2 = data.Obs2(seasons == 1); 
summer_2 = data.Obs2(seasons == 2); 
autumn_2 = data.Obs2(seasons == 3); 
winter_2 = data.Obs2(seasons == 4); 
spring_3 = data.Obs3(seasons == 1); 
summer_3 = data.Obs3(seasons == 2); 
autumn_3 = data.Obs3(seasons == 3); 
winter_3 = data.Obs3(seasons == 4); 

plot_data = [ 
    spring_1; 
    summer_1; 
    autumn_1; 
    winter_1; 
    spring_2; 
    summer_2; 
    autumn_2; 
    winter_2; 
    spring_3; 
    summer_3; 
    autumn_3; 
    winter_3 
]; 

plot_groups = [ 
    (1 * ones(size(spring_1))) (1 * ones(size(spring_1))); 
    (1 * ones(size(summer_1))) (2 * ones(size(summer_1))); 
    (1 * ones(size(autumn_1))) (3 * ones(size(autumn_1))); 
    (1 * ones(size(winter_1))) (4 * ones(size(winter_1))); 
    (2 * ones(size(spring_2))) (5 * ones(size(spring_2))); 
    (2 * ones(size(summer_2))) (6 * ones(size(summer_2))); 
    (2 * ones(size(autumn_2))) (7 * ones(size(autumn_2))); 
    (2 * ones(size(winter_2))) (8 * ones(size(winter_2))); 
    (3 * ones(size(spring_3))) (9 * ones(size(spring_3))); 
    (3 * ones(size(summer_3))) (10 * ones(size(summer_3))); 
    (3 * ones(size(autumn_3))) (11 * ones(size(autumn_3))); 
    (3 * ones(size(winter_3))) (12 * ones(size(winter_3))) 
]; 

labels_obs = {'' '' '' '' '' '' '' '' '' '' '' ''}; 
labels_season = repmat({'Spring' 'Summer' 'Autumn' 'Winter'},1,3); 

figure('Units','normalized','Position',[0.05 0.1 0.9 0.8]); 
boxplot(plot_data,plot_groups, ... 
    'BoxStyle','outline', ... 
    'FactorGap',[5 1], ... 
    'Labels',{labels_obs; labels_season}, ... 
    'Notch','on'); 

colors = repmat('wcyg',1,3); 
h = findobj(gca,'Tag','Box'); 

for i = 1:numel(h) 
    patch(get(h(i),'XData'),get(h(i),'YData'),colors(i),'FaceAlpha',0.5); 
end 

h = findall(allchild(findall(gca,'Type','hggroup')),'Type','text','String',''); 
positions = cell2mat(get(h,'pos')); 
positions_new = num2cell([mean(reshape(positions(:,1),4,[]))' positions(1:4:end,2:end)],2); 
set(h(1:4:end),{'Position'},positions_new,{'String'},{'Observations 3'; 'Observations 2'; 'Observations 1'}) 

h = findall(allchild(findall(gca,'Type','hggroup')),'Type','text','String',''); 
delete(h); 

Ergebnis:

Result Update