JohnCoene / echarts4r

🐳 ECharts 5 for R
http://echarts4r.john-coene.com/
Other
595 stars 81 forks source link

e_error_bar changes intervals on x-axis #455

Closed milesmedina closed 2 years ago

milesmedina commented 2 years ago

Hi John,

I've only just started working with eCharts4r this week, and it's awesome! I am however seeing some unexpected behavior when adding error bars to my chart with e_error_bar().

The code below specifies some made-up values and produces a chart with error bars.

library(tidyr);  library(dplyr);  library(echarts4r)

means <- data.frame( Date = seq.Date( as.Date('2020-01-01'),
                                      as.Date('2020-10-31'),
                                      by = 'month'),

                     Value = c(4,6,5,4,6,
                               8,7,5,7,6),
                     Type = rep("Mean",10)
)
means$lwr <- means$Value-1.5
means$upr <- means$Value+1.5

trend.10 <- data.frame( Date = seq.Date( as.Date('2020-01-01'),
                                         as.Date('2020-09-30'),
                                         length.out=50 ),
                        Value = seq(4.5,6.5,length.out=50),
                        Type = rep("Trend10",50) )
trend.5 <- data.frame( Date = seq.Date( as.Date('2020-06-01'),
                                        as.Date('2020-09-30'),
                                        length.out=50 ),
                       Value = seq(6.2,6.7,length.out=50),
                       Type = rep("Trend5",50) )
trends  <- full_join( trend.5, trend.10, by = c("Date","Value","Type") )
test.df <- full_join( means, trends, by = c("Date","Value","Type") )
test.df <- test.df[ order(test.df$Date), ]
test.df <- pivot_wider( test.df, names_from=Type, values_from=Value )

test.df %>% 
  e_charts(x=Date) %>% 
  e_line( serie = Mean
        , lineStyle = list(width=0)
         ) %>% 
  e_error_bar( lower = lwr
             , upper = upr
             )

If you run the code without the e_error_bar() call, the chart looks like this, with the Mean values appropriately spaced along the x-axis (Date): image

Running the code with the e_error_bar() call, the chart displays error bars, but the spacing of the Mean values is different, with the first five values closer together than the last five: image

I am guessing that the spacing of Mean values is related to the NAs in the Mean column: The first five Mean values are more spaced out by NAs than the last five in the dataframe itself, due to the join with the Trend5 and Trend10 values. But I don't understand why this spacing in the dataframe would affect the spacing on the axis. This only seems to happen when there is an e_error_bar() call. The x-axis spacing is not affected if, for instance, I instead call e_line() to display one of the trend lines (e.g. %>% e_line( serie = Trend10, collapseNulls = TRUE )).

> test.df %>% as.data.frame()
          Date lwr upr Mean  Trend10   Trend5
1   2020-01-01 2.5 5.5    4       NA       NA
2   2020-01-01  NA  NA   NA 4.500000       NA
3   2020-01-06  NA  NA   NA 4.540816       NA
4   2020-01-12  NA  NA   NA 4.581633       NA
5   2020-01-17  NA  NA   NA 4.622449       NA
6   2020-01-23  NA  NA   NA 4.663265       NA
7   2020-01-28  NA  NA   NA 4.704082       NA
8   2020-02-01 4.5 7.5    6       NA       NA
9   2020-02-03  NA  NA   NA 4.744898       NA
10  2020-02-09  NA  NA   NA 4.785714       NA
11  2020-02-14  NA  NA   NA 4.826531       NA
12  2020-02-20  NA  NA   NA 4.867347       NA
13  2020-02-25  NA  NA   NA 4.908163       NA
14  2020-03-01 3.5 6.5    5       NA       NA
15  2020-03-02  NA  NA   NA 4.948980       NA
16  2020-03-07  NA  NA   NA 4.989796       NA
17  2020-03-13  NA  NA   NA 5.030612       NA
18  2020-03-19  NA  NA   NA 5.071429       NA
19  2020-03-24  NA  NA   NA 5.112245       NA
20  2020-03-30  NA  NA   NA 5.153061       NA
21  2020-04-01 2.5 5.5    4       NA       NA
22  2020-04-04  NA  NA   NA 5.193878       NA
23  2020-04-10  NA  NA   NA 5.234694       NA
24  2020-04-15  NA  NA   NA 5.275510       NA
25  2020-04-21  NA  NA   NA 5.316327       NA
26  2020-04-27  NA  NA   NA 5.357143       NA
27  2020-05-01 4.5 7.5    6       NA       NA
28  2020-05-02  NA  NA   NA 5.397959       NA
29  2020-05-08  NA  NA   NA 5.438776       NA
30  2020-05-13  NA  NA   NA 5.479592       NA
31  2020-05-19  NA  NA   NA 5.520408       NA
32  2020-05-24  NA  NA   NA 5.561224       NA
33  2020-05-30  NA  NA   NA 5.602041       NA
34  2020-06-01 6.5 9.5    8       NA       NA
35  2020-06-01  NA  NA   NA       NA 6.200000
36  2020-06-03  NA  NA   NA       NA 6.210204
37  2020-06-05  NA  NA   NA 5.642857       NA
38  2020-06-05  NA  NA   NA       NA 6.220408
39  2020-06-08  NA  NA   NA       NA 6.230612
40  2020-06-10  NA  NA   NA 5.683673       NA
41  2020-06-10  NA  NA   NA       NA 6.240816
42  2020-06-13  NA  NA   NA       NA 6.251020
43  2020-06-15  NA  NA   NA       NA 6.261224
44  2020-06-16  NA  NA   NA 5.724490       NA
45  2020-06-18  NA  NA   NA       NA 6.271429
46  2020-06-20  NA  NA   NA       NA 6.281633
47  2020-06-21  NA  NA   NA 5.765306       NA
48  2020-06-23  NA  NA   NA       NA 6.291837
49  2020-06-25  NA  NA   NA       NA 6.302041
50  2020-06-27  NA  NA   NA 5.806122       NA
51  2020-06-28  NA  NA   NA       NA 6.312245
52  2020-06-30  NA  NA   NA       NA 6.322449
53  2020-07-01 5.5 8.5    7       NA       NA
54  2020-07-02  NA  NA   NA 5.846939       NA
55  2020-07-03  NA  NA   NA       NA 6.332653
56  2020-07-05  NA  NA   NA       NA 6.342857
57  2020-07-08  NA  NA   NA       NA 6.353061
58  2020-07-08  NA  NA   NA 5.887755       NA
59  2020-07-10  NA  NA   NA       NA 6.363265
60  2020-07-12  NA  NA   NA       NA 6.373469
61  2020-07-14  NA  NA   NA 5.928571       NA
62  2020-07-15  NA  NA   NA       NA 6.383673
63  2020-07-17  NA  NA   NA       NA 6.393878
64  2020-07-19  NA  NA   NA 5.969388       NA
65  2020-07-20  NA  NA   NA       NA 6.404082
66  2020-07-22  NA  NA   NA       NA 6.414286
67  2020-07-25  NA  NA   NA 6.010204       NA
68  2020-07-25  NA  NA   NA       NA 6.424490
69  2020-07-27  NA  NA   NA       NA 6.434694
70  2020-07-30  NA  NA   NA       NA 6.444898
71  2020-07-30  NA  NA   NA 6.051020       NA
72  2020-08-01 3.5 6.5    5       NA       NA
73  2020-08-01  NA  NA   NA       NA 6.455102
74  2020-08-04  NA  NA   NA       NA 6.465306
75  2020-08-05  NA  NA   NA 6.091837       NA
76  2020-08-06  NA  NA   NA       NA 6.475510
77  2020-08-09  NA  NA   NA       NA 6.485714
78  2020-08-10  NA  NA   NA 6.132653       NA
79  2020-08-11  NA  NA   NA       NA 6.495918
80  2020-08-14  NA  NA   NA       NA 6.506122
81  2020-08-16  NA  NA   NA 6.173469       NA
82  2020-08-16  NA  NA   NA       NA 6.516327
83  2020-08-19  NA  NA   NA       NA 6.526531
84  2020-08-21  NA  NA   NA       NA 6.536735
85  2020-08-22  NA  NA   NA 6.214286       NA
86  2020-08-23  NA  NA   NA       NA 6.546939
87  2020-08-26  NA  NA   NA       NA 6.557143
88  2020-08-27  NA  NA   NA 6.255102       NA
89  2020-08-28  NA  NA   NA       NA 6.567347
90  2020-08-31  NA  NA   NA       NA 6.577551
91  2020-09-01 5.5 8.5    7       NA       NA
92  2020-09-02  NA  NA   NA 6.295918       NA
93  2020-09-02  NA  NA   NA       NA 6.587755
94  2020-09-05  NA  NA   NA       NA 6.597959
95  2020-09-07  NA  NA   NA 6.336735       NA
96  2020-09-07  NA  NA   NA       NA 6.608163
97  2020-09-10  NA  NA   NA       NA 6.618367
98  2020-09-12  NA  NA   NA       NA 6.628571
99  2020-09-13  NA  NA   NA 6.377551       NA
100 2020-09-15  NA  NA   NA       NA 6.638776
101 2020-09-17  NA  NA   NA       NA 6.648980
102 2020-09-18  NA  NA   NA 6.418367       NA
103 2020-09-20  NA  NA   NA       NA 6.659184
104 2020-09-22  NA  NA   NA       NA 6.669388
105 2020-09-24  NA  NA   NA 6.459184       NA
106 2020-09-25  NA  NA   NA       NA 6.679592
107 2020-09-27  NA  NA   NA       NA 6.689796
108 2020-09-30  NA  NA   NA 6.500000 6.700000
109 2020-10-01 4.5 7.5    6       NA       NA

Any advice? Thanks!

helgasoft commented 2 years ago

Yes, NAs do affect the display and lines are getting interrupted. But spacing on both axes is correct, I think.

test.df |>
  e_charts(x= Date) |>
  e_scatter(serie= Mean, symbolSize= 8) |> 
  e_line(serie= Trend10) |>
  e_line(serie= Trend5) |> 
  e_error_bar(lower= lwr, upper= upr)

image

milesmedina commented 2 years ago

Hi helgasoft,

Thanks for your response. Because the x-axis is time (dates), I need the x-axis to be spaced temporally regardless of the spacing of data within the dataframe. The appropriate spacing can be achieved without calling e_error_bar(): The Mean and Trend10 points are spaced evenly, and therefore the Trend10 series appears as a straight line as it should:

  e_charts(x= Date) |>
  e_scatter(serie= Mean, symbolSize= 8) |> 
  e_line(serie= Trend10) |>
  e_line(serie= Trend5)

image

I also notice that in your plot, the error bars are slightly offset to the right of the Mean points, when they should line up on center.

helgasoft commented 2 years ago

2011 to 2020 ? that's not the same data. Could you provide the entire code please? " error bars are slightly offset to the right of the Mean points" - yes, that's how they are, kind of hard to fix.

milesmedina commented 2 years ago

Ah, yes, you're right. I changed the Date series after the original post to more accurately reflect the data I'm actually working with, but it is essentially the same input and doesn't change the core issue. Here is the code with the revised dates:

library(tidyr);  library(dplyr);  library(echarts4r)

means <- data.frame( Date = seq.Date( as.Date('2011-01-01'),
                                      as.Date('2020-12-31'),
                                      by = 'year'),

                     Value = c(4,6,5,4,6,
                               8,7,5,7,6),
                     Type = rep("Mean",10)
)
means$lwr <- means$Value-1.5
means$upr <- means$Value+1.5

trend.10 <- data.frame( Date = seq.Date( as.Date('2011-01-01'),
                                         as.Date('2020-12-31'),
                                         length.out=50 ),
                        Value = seq(4.5,6.5,length.out=50),
                        Type = rep("Trend10",50) )
trend.5 <- data.frame( Date = seq.Date( as.Date('2016-01-01'),
                                        as.Date('2020-12-31'),
                                        length.out=50 ),
                       Value = seq(6.7,6.2,length.out=50),
                       Type = rep("Trend5",50) )
trends  <- full_join( trend.5, trend.10, by = c("Date","Value","Type") )
test.df <- full_join( means, trends, by = c("Date","Value","Type") )
test.df <- test.df[ order(test.df$Date), ]
test.df <- pivot_wider( test.df, names_from=Type, values_from=Value )

test.df |>
  e_charts(x= Date) |>
  e_scatter(serie= Mean, symbolSize= 8) |> 
  e_line(serie= Trend10) |>
  e_line(serie= Trend5) # |>
  # e_error_bar(lower= lwr, upper= upr)
helgasoft commented 2 years ago

ok, understand the problem, but do not know how to fix it in echarts4r. Here is a solution with a similar library.

library(echarty)
tmp <- test.df |> relocate(Date,Mean) |> mutate(Date= as.character(Date))
ec.init(load='custom', preset=FALSE, 
      xAxis= list(type='time', data= tmp$Date, boundaryGap= c('5%','5%')), 
      yAxis= list(show=TRUE),
      series= list(
  list(type='scatter', name='Mean', data= ec.data(tmp |> select(Date,Mean) |> na.omit())),
  list(type='line', name='Trend10', data= ec.data(tmp |> select(Date,Trend10) |> na.omit())),
  list(type='line', name='Trend5',  data= ec.data(tmp |> select(Date,Trend5) |> na.omit()))
)) |> 
ecr.ebars(tmp)

If "|> na.omit()" is removed, the lines will get broken because of NAs. image

milesmedina commented 2 years ago

Incredible! You're a lifesaver! Thanks so much!!!

milesmedina commented 2 years ago

Oops I just realized I did not provide the code with the revised dates above... sorry! And thanks again I've edited the previous post with the correct code

helgasoft commented 2 years ago

This could be the fix for echarts4r

test.df |>
  e_charts(x= Date) |>
  e_scatter(serie= Mean, symbolSize= 8) |> 
  e_line(serie= Trend10) |>
  e_line(serie= Trend5) |>
  e_error_bar(lower= lwr, upper= upr) |> 
  e_x_axis(type='time')    # change X-axis from 'category' to 'time'

image

milesmedina commented 2 years ago

Thanks! I had tried this with the e_x_axis() call closer to the top (didn't work), but it didn't occur to me to move it down below the e_error_bar() call

helgasoft commented 2 years ago

Well, the _e_xaxis() call shouldn't even be there, but _e_errorbar improperly sets the chart type to 'category', so it's is a fix for that.