rte-antares-rpackage / manipulatewidget Goto Github PK
View Code? Open in Web Editor NEWAdd More Interactivity to htmlwidgets
Add More Interactivity to htmlwidgets
User should be able to dynamically show/hide groups of inputs in the same way he can show or hide individual inputs:
manipulateWidget(
myPlotFun(x, y),
group = list(
x = mwNumeric(0),
y = mwNumeric(0)
),
showGroup = mwCheckbox(),
.display = list(group = showGroup)
)
Have something similar to .display
to update the choices of a selectInput
Ça pourrait notamment servir à placer des légendes ou des commentaires
Hi, I'm trying to control the options
argument in the mwSelectize function, specifically the maxItems
argument in options
argument via mwSelect input.
Here is the sample code and got error emssage when changing the selection of max
.
Any ideas to solve this issue? Thanks.
require(manipulateWidget)
manipulateWidget(
NA,
max = mwSelect(choices = c(1:5)),
select = mwSelectize(choices = c(1:5), multiple = T,
options = list(maxItems = max)
)
)
Warning: Error in <Anonymous>: unused argument (options = list(2))
54: do.call
53: <Anonymous>
51: input$updateHTML
50: updateHTML
49: updateRevDeps
48: inputList$setValue
47: controller$setValueById
46: <observer>
3: shiny::runApp
2: shiny::runGadget
1: manipulateWidget
Dear users,
I've tried to create combined HTM widget by invoking:
htmlwidgets::saveWidget(manipulateWidget::combineWidgets(as.htmlwidget(ft), p ), "consolidated.html")
Where ft is output from formattable
and p graph from plotly
.
The table has lost most of CSS features such as grids display.
Would you please hint me how to add/preserve css attributes from the ft?
Thanks!
Content should be different in the two files
Compare two interactive charts, one above the other (or one next to the other). Som inputs should be common to both, and some should have a distinct value for each chart.
Currently only the choices of select inputs can be modified dynamically. This mecanism should be generalized to every parameter of every input.
For instance, there is a map combined with time series plot and I want to update the map (without overwriting it) and redraw the time series. How to do it ?
When I Host manipulateWidget using R Plumber it gives the following Error.
Error:
<simpleError in get(fun, mode = "function", envir = parent.frame()): object 'shiny' of mode 'function' was not found>
<simpleError in system.file(config, package = package): 'package' must be of length 1>
code:-
File Name:- html_widget.R
#' @get /plotly
#' @serializer htmlwidget
library(plotly)
data(iris)
library(plumber)
library(manipulateWidget)
varNames <- names(iris)[1:4]
plotlygraph <- function(){manipulateWidget(
plotClusters(xvar, yvar, nclusters),
xvar = mwSelect(varNames),
yvar = mwSelect(varNames, value = "Sepal.Width"),
nclusters = mwSlider(1, 10, value = 3),
plot_ly(x = ~iris[[xvar]], y = ~iris[[yvar]], color = ~clusters,
type = "scatter", mode = "markers") %>%
layout(xaxis = list(title=xvar), yaxis = list(title=yvar))
)
}
r <- plumber::plumb("html_widget.R")
r$run(host="0.0.0.0", port=8000)
regards,
Mahesh Kulkarni
I'm trying to install this package on an HPC system in gnu/R 3.5.0 and I get an error that it can't load a shared object in my local R library.
libimf.so: cannot open shared object file: No such file or directory
ERROR: lazy loading failed for package 'manipulateWidget'
{manipulateWidget} is not working for RStudio's {gt} package:
Given the following two files as input for {gt} and {DiagrammeR} we will try and use the package to display both widgets next to each other:
A text file result.txt
:
entity information
"**_statTest** ; The statistical test performed to interpret the results of the study. _e.g._ **Linear Regression**, **Logistic Regression**, **Gene Burden Test (SKAT)**, **Gene Burden Test (cmcWald)**, **Survival (SKAT)**, **Survival (Burden)**" Logisitc Regression
"**_metaAnalysisTestType** ; The type of meta-analysis run. Values must be one of: **Cochran's Q Test**, **Fixed Effects**, **Random Effects**, **Fixed Effects and Random Effects**", **Unknown**, and **NA**
**_sampleSizeTotal** ; The sample size (N) of total observations 216257
**_numGenotypesPerMarker** ; The number of genotypes per marker used for the statistical test of association. This may be different from the sample size of the subjects since some genotypes may fail QC _NA_
**_pValue_** ; A quantitative confidence value that represents the probability of obtaining a result at least as extreme as that actually obtained assuming that the actual value was the result of chance alone. This version will transform any values <=5e-324 to 5e-324 (the lower limit of double values) 0.04726
"**_pValueOrig** ; The [pValueOrig](http://purl.obolibrary.org/obo/OBI_0000175) quantitative confidence value that represents the probability of obtaining a result at least as extreme as that actually obtained, assuming that the actual value was the result of chance alone. This version will contain the raw values provided in string format to avoid any float conversion errors" 0.04726
**_standardError** ; The [standard error](https://en.wikipedia.org/wiki/Standard_error) of a statistic is the standard deviation of its sampling distribution 0.0607
**_zScore** ; A [z-score](https://en.wikipedia.org/wiki/Standard_score) is the signed number of standard deviations by which the value of an observation or data point differs from the mean value of what is being observed or measured NA
**_oddsRatio** ; [oddsRatio](https://en.wikipedia.org/wiki/Odds_ratio) is the quantification of how strongly the presence or absence of property A is associated with the presence or absence of property B in a given population 0.8865657
**_beta** ; The [beta coefficient](https://www.listendata.com/2015/04/standardized-vs-unstandardized.html). It represents the amount by which dependent variable changes if we change independent variable by one unit keeping other independent variables constant -0.1204
"**_bayesFactor** ; The [Bayes factor](https://en.wikipedia.org/wiki/Bayes_factor) is a ratio of the likelihood probability of two competing hypotheses, usually a null and an alternative" _NA_
**_fdr** ; The False Discovery Rate (FDR) of a set of predictions is the expected percent of false predictions in the set of predictions _NA_
**_ciLower** ; The lower bound of a [confidence interval](https://en.wikipedia.org/wiki/Confidence_interval) _NA_
**_ciUpper** ; The upper bound of a [confidence interval](https://en.wikipedia.org/wiki/Confidence_interval) _NA_
"**_ciPercentile** ; The percentile used for determining a confidence interval. If this field is filled in, then ciUper and ciLower must be filled in" _NA_
**_numBurdenMarkers** ; The number of markers examined for the statistical test performed in a gene burden test _NA_
**_isPrimaryAnalysisPValue** ; A boolean value that indicates if the values in this entity (_i.e._ `pValue`) should be used as the main results when examining a gene in a dataset for GERMLINE scoring algorithms TRUE
**_copyNumber** ; The number of measured copies found for a specific Copy Number Variation (CNV) marker _NA_
"**_hazardRatio** ; In survival analysis, the [hazard ratio](https://en.wikipedia.org/wiki/Hazard_ratio) (HR) is the ratio of the hazard rates corresponding to the conditions described by two levels of an explanatory variable" _NA_
**_effectDirection** ; The direction of effect that a marker or allele has on a trait. Two possible values (**+** or **-**). In the context of a _case/control_ analysis **+** implies increased risk **-** implies decreased risk ; in the context of a _quantitative trait_ **+** means increased value **-** means decreased value **-**
**cochranQStat** ; The test statistic for a Cochran's Q Test for heterogeneity of effect sizes. [Cochran's Q test](https://www.itl.nist.gov/div898/software/dataplot/refman1/auxillar/cochran.htm) is a non-parametric statistical test to verify whether k treatments have identical effects _NA_
And a edr.gv
file like:
digraph Association{
node [shape=box, style=rounded]
Lorem -> ipsum
dolor -> sit
sit -> amet
amet -> Lorem
amet -> consectetur
amet -> adipiscing
amet -> elit
Lorem -> sed [optional="true"]
sed -> Lorem [optional="true"]
Lorem -> do
do -> eiusmod [optional="true"]
do -> tempor [optional="true"]
do -> incididunt [optional="true"]
ut -> do [optional="true"]
do -> labore [optional="true"]
git -> labore [optional="true"]
do -> et
et -> do
ipsum -> et
dolore -> ipsum [optional="true"]
magna -> ipsum [optional="true"]
ipsum -> aliqua [optional="true"]
ipsum -> enim [optional="true"]
}
We will try and place a {gt} table next to the diagram
library(vroom)
library(gt)
# load table
entity_table <- vroom::vroom("result.txt", delim = "\t")
# create table and diagram
table <- entity_table %>%
mutate(entity = str_replace_all(entity, ";", "<br>")) %>%
gt() %>%
fmt_markdown(columns = everything()) %>%
tab_header(
title = md("**Lorem**"),
subtitle = md("Lorem ipsum is a placeholder text commonly used to demonstrate the visual form of a document or a typeface without relying on meaningful content.")
) %>%
tab_options(
column_labels.hidden = TRUE,
table.font.size = px(12L)
) %>%
fmt_missing(
columns = 1:2,
missing_text = "---"
)
table
library(DiagrammeR)
diagram <- DiagrammeR::grViz('edr.gv')
library(manipulateWidget)
combineWidgets(ncol=2, table, diagram)
library(manipulateWidget)
combineWidgets(ncol=2, diagram, diagram)
Hi all,
Firstly thanks to the developers for this package which is very useful. The issue I have found is that when using the package it does not seem to be possible to use DT datatables in the combine widgets command.
Is it possible to integrate the data table into a single view alongside other widgets using the combine widgets command? If so, how can this be done? And, if not, why not?
This is what i've tried but the data table does not show up:
library(manipulateWidget)
library(plotly)
library(DT)
if (require(plotly)) {
data(iris)
combineWidgets(title = "The iris data set: sepals", ncol = 2, colsize = c(2,1),
plot_ly(iris, x = ~Sepal.Length, y = ~Sepal.Width, type = "scatter",
mode = "markers", color = ~Species),
datatable(iris)
)
}
Thanks in advance. :)
Great package!
Is it possible to add e.g. radioboxes to an htmlwidget embedded in an html document rendered by r markdown? I mean can it be added to the rendered html page without using shiny? I haven't succeeded yet in doing so, but is it even possible?
Kind regards
The rgl
package commonly has several widgets in a display that need to communicate with each other. Recently I've added crosstalk
support, so this will become more common.
Older rgl
code used magrittr
pipes to glue together widgets in an htmltools::tagList
. I've been experimenting with using combineWidgets
instead of a tagList
, and this looks very promising, because things are automatically resized to fit the available space. (Issue #46 was related to this.).
I've been working out a simple model. If w1
, w2
, and w3
are functions producing widgets, then w1() %>% w2() %>% w3()
should end up something like combineWidgets(w1(), w2(), w3())
, except that the 2nd and 3rd widgets will see what came before, so they can set up communications.
This requires a few hacks. I'm hoping that some of these things could be supported so I don't need the hacks.
w1() %>% w2()
is going to produce a combineWidgets
object (call it c12
) which will be passed into w3()
. That would be okay, but it makes w3
's job tricky to see the earlier ones, and it gets worse if there's a longer pipeline. Currently I'm grabbing the c12$widgets
element and assuming it's basically a list containing unmodified copies of the original widgets, then constructing a new combined widget by putting those two widgets together with w3()
in a single call using do.call(combineWidgets, c(c12$widgets, list(w3(), ncol = 1)))
. It would be nice if there were an appendWidget
function to allow this in a less hacky way.
Another problem is that not all widgets are the same size. Some (like rglwidget()
or leaflet()
) are pretty big, while others (like crosstalk::filter_slider
) have fairly small heights. I'd like to have the sizing happen somewhat automatically (with the possibility for a user to override it), so I need to construct a rowsize
vector for the combineWidgets
call. I've been grabbing the old rowsize
(e.g. c12$params$rowsize
in the example above) and adding one more entry to it in the new combineWidgets
call. Perhaps the hypothetical appendWidget
function could do something similar.
Finally, I'm having trouble guessing at what size to put into the new rowsize
vector. Mostly those sizes are determined in Javascript once the target location of the widgets is known, but it would be really nice to have a function that could guess what would happen, based on a default target location, and the sizingPolicy
of the widget.
Hi,
I'm trying to control the .compareOpts
argument in the manipulateWidget package, specifically the
ncharts
, nrow
and ncol
arguments of the compareOptions
function via shiny inputs, specifically, sliderInput
. I have tried using the code snippet below, but I keep getting error messages.
Code
require(shiny)
require(dygraphs)
require(pipeR)
require(manipulateWidget)
ui <- fillPage(
fillRow(
flex = c(NA, 1),
div(
textInput("title", label = "Title", value = "glop"),
sliderInput("obs", "Number of observations:",
min = 10, max = 1000, value = 500),
sliderInput("ncharts", label = "Select number of charts to view", min = 1, max = 6, step = 1, value = 8),
sliderInput("nrow", label = "Select number of rows to view", min = 1, max = 6, step = 1, value = 4),
sliderInput("ncol", label = "Select number of columns to view", min = 1, max = 6, step = 1, value = 3)
),
mwModuleUI("ui", height = "100%")
)
)
server <- function(input, output, session) {
data <- reactive({
if(runif(1) > 0.5){
data.frame(
year = 2000+1:input$obs,
series1 = rnorm(input$obs),
series2 = rnorm(input$obs),
series3 = rnorm(input$obs)
)
} else {
data.frame(
year = 2000+1:input$obs,
series1 = rnorm(input$obs),
series2 = rnorm(input$obs)
)
}
})
c <- manipulateWidget(
{
dygraph(data[range[1]:range[2] - 2000, c("year", series)], main = title)
},
range = mwSlider(min = 2001, max = 2001 + (nrow(data)-1), c(2001, 2001 + (nrow(data)-1))),
series = mwSelect(choices = colnames(data)[-1], value = colnames(data)[3]),
title = mwSharedValue(),
data = mwSharedValue(), .runApp = FALSE,
.compare = "range",
.compareOpts = compareOptions(ncharts = input$ncharts, nrow = input$nrow, ncol = input$ncol)
)
mwModule("ui", c, title = reactive(input$title), data = data)
}
shinyApp(ui, server)
Error message
Error in .getReactiveEnvironment()$currentContext() :
Operation not allowed without an active reactive context. (You tried to do something that can only be done from inside a reactive expression or observer.)
I've also tried to add sliders for ncharts, nrow and ncol arguments to the manipulateWidget gadget in the code below but still get errors.
Code
c <- manipulateWidget(
{
dygraph(data[range[1]:range[2] - 2000, c("year", series)], main = title)
},
range = mwSlider(min = 2001, max = 2001 + (nrow(data)-1), c(2001, 2001 + (nrow(data)-1))),
series = mwSelect(choices = colnames(data)[-1], value = colnames(data)[3]),
title = mwSharedValue(),
ncharts = mwSlider(min = 1, max = 10, value = 4),
nrow = mwSlider(min = 1, max = 10, value = 4),
ncol = mwSlider(min = 1, max = 10, value = 4),
data = mwSharedValue(), .runApp = FALSE,
.compare = "range",
.compareOpts = compareOptions(ncharts = "ncharts", nrow = "nrow", ncol = "ncol")
)
mwModule("ui", c, title = reactive(input$title),
ncharts = reactive(input$ncharts),
ncol = reactive(input$mcol),
nrow = reactive(input$nrow),
data = data)
Error
Warning: Error in *: non-numeric argument to binary operator
Stack trace (innermost first):
39: .getRowAndCols
38: manipulateWidget
37: server [C:/Users/jla995/Documents/Work Projects/R - Panel Plots in Shiny.R#41]
1: runApp
Error in nrow * ncol : non-numeric argument to binary operator
When I create a separate arguments for the 3 parameters like below, the app works but this isn't what I want. I would like for the user to have the ability to change the number and layout of the charts as they see fit.
ncharts = 10
nrow = 4
ncol = 3
Session info
R version 3.4.0 (2017-04-21)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows >= 8 x64 (build 9200)
Matrix products: default
locale:
[1] LC_COLLATE=English_United States.1252 LC_CTYPE=English_United States.1252 LC_MONETARY=English_United States.1252 LC_NUMERIC=C
[5] LC_TIME=English_United States.1252
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] manipulateWidget_0.8.0 pipeR_0.6.1.3 dygraphs_1.1.1.4 shiny_1.0.5 rAmCharts_2.1.5
loaded via a namespace (and not attached):
[1] Rcpp_0.12.12 lattice_0.20-35 zoo_1.8-0 digest_0.6.12 mime_0.5 grid_3.4.0 R6_2.2.2 xtable_1.8-2
[9] magrittr_1.5 miniUI_0.1.1 data.table_1.10.4 tools_3.4.0 htmlwidgets_0.9 httpuv_1.3.5 yaml_2.1.14 compiler_3.4.0
[17] htmltools_0.3.6
I appreciate any help to get this working?
Thanks.
Salut @bthieurmel,
Le commit ci-dessous introduit quelques bugs:
Est-ce que tu te souviens de pourquoi tu avais fait ça ? Tu as un cas d'usage en tête ?
commit fc5740c
Author: Benoit Thieurmel [email protected]
Date: Tue Sep 5 15:01:07 2017 +0200
can now pass value as expr (and can depend of sharedValue or current variable) +fix dateRange control
For now, user has to use parameters .display and .updateInputs which are a bit complicated to use. A simpler API would be to pass directly expressions in the input generator function. For instance the following code:
manipulateWidget(
plotCar(car),
cylinders = mwSelect(c("4", "6", "8")),
car = mwSelect(),
.updateInputs = list(
car = list(choices = carChoices[[cylinders]])
)
)
could be replaced by:
manipulateWidget(
plotCar(car),
cylinders = mwSelect(c("4", "6", "8")),
car = mwSelect(choices = carChoices[[cylinders]]),
)
``
Pour combiner plusieurs widgets on pourrait soit passer directement les widgets soit passer une liste contenant les-dits widgets:
combineWidgets(w1, w2)
# équivalent à
l <- list(w1, w2)
combineWidgets(list = l)
I'm not sure if this is a crosstalk
issue or a manipulateWidget
issue, but if I write e.g.
library(crosstalk)
library(manipulateWidget)
sd <- SharedData$new(mtcars)
combineWidgets(filter_slider("mpg", "Miles per gallon", sd, "mpg"))
the slider doesn't appear to get initialized properly, I just get a simple label and input box. (The real case has several widgets as well as the filter_slider
, of course.)
This is using crosstalk 1.0.1
and manipulateWidget 0.8.0
, both current on Github.
I'll post a link to this issue on the crosstalk
repos.
Hi,
I wanted to manipulateWidget::combineWidgets
to create the following plot
I tried to implement this using the following R code
library(plotly)
#> Loading required package: ggplot2
#>
#> Attaching package: 'plotly'
#> The following object is masked from 'package:ggplot2':
#>
#> last_plot
#> The following object is masked from 'package:stats':
#>
#> filter
#> The following object is masked from 'package:graphics':
#>
#> layout
library(ggplot2)
library(magrittr)
data <- head(ggplot2::diamonds)
fig1 <- plotly::plot_ly(
type = 'table',
columnwidth = c(100, 100),
columnorder = c(0, 1),
header = list(
values = c("Cut","Price"),
align = c("center", "center"),
line = list(width = 1, color = 'black'),
fill = list(color = c("grey", "grey")),
font = list(family = "Arial", size = 14, color = "white")
),
cells = list(
values = rbind(data$cut, data$price),
align = c("center", "center"),
line = list(color = "black", width = 1),
font = list(family = "Arial", size = 12, color = c("black"))
))
cut_name <- data %>%
dplyr::pull(.data[["cut"]]) %>%
unique() %>%
as.character()
cut_pal <- c("#377eb8","#b72e92","#322eb7","#b7772e") %>%
stats::setNames(cut_name)
fig2 <- plotly::plot_ly() %>%
plotly::add_trace(data = data,
x = data[["cut"]],
y = data[["price"]],
color = data[["cut"]],
colors = cut_pal,
type = "scatter",
mode = 'markers')
fig <- manipulateWidget::combineWidgets(list = list(fig2, fig1))
fig
#> Input to asJSON(keep_vec_names=TRUE) is a named vector. In a future version of jsonlite, this option will not be supported, and named vectors will be translated into arrays instead of objects. If you want JSON object output, please use a named list instead. See ?toJSON.
Created on 2021-08-17 by the reprex package (v2.0.1)
Unfortunately, it gives this warning message "Input to asJSON(keep_vec_names=TRUE) is a named vector. In a future version of jsonlite, this option will not be supported, and named vectors will be translated into arrays instead of objects. If you want JSON object output, please use a named list instead. See ?toJSON."
Strangely, if I did not put in any custom colors to the plot,
library(plotly)
#> Loading required package: ggplot2
#>
#> Attaching package: 'plotly'
#> The following object is masked from 'package:ggplot2':
#>
#> last_plot
#> The following object is masked from 'package:stats':
#>
#> filter
#> The following object is masked from 'package:graphics':
#>
#> layout
library(ggplot2)
library(magrittr)
data <- head(ggplot2::diamonds)
fig1 <- plotly::plot_ly(
type = 'table',
columnwidth = c(100, 100),
columnorder = c(0, 1),
header = list(
values = c("Cut","Price"),
align = c("center", "center"),
line = list(width = 1, color = 'black'),
fill = list(color = c("grey", "grey")),
font = list(family = "Arial", size = 14, color = "white")
),
cells = list(
values = rbind(data$cut, data$price),
align = c("center", "center"),
line = list(color = "black", width = 1),
font = list(family = "Arial", size = 12, color = c("black"))
))
fig2 <- plotly::plot_ly() %>%
plotly::add_trace(data = data,
x = data[["cut"]],
y = data[["price"]],
type = "scatter",
mode = 'markers')
fig <- manipulateWidget::combineWidgets(list = list(fig2, fig1))
fig
Created on 2021-08-17 by the reprex package (v2.0.1)
The message is not present and the plot is as follows:
Any idea what is the cause of this error message ? The message seems to indicate that my implementation will not work in the future. Is there any way to avoid this ?
Thank you.
We must add tests, maybe we can use RSelenium
https://cran.r-project.org/web/packages/RSelenium/vignettes/shinytesting.html
https://cran.r-project.org/web/packages/RSelenium/index.html
Rajouter dans le README une section "contribute" et expliquer comment reconstruire le site avec la doc
User should be able to access each widget and modify it.
htmlwidgets creates a class for the div holding a widget that contains the name of the widget, and some other stuff. combineWidgets just uses class cw-widget
, ignoring the original class.
This causes trouble for rgl
, because it provides some style info in a CSS file that depends on the class attribute for the div.
I have a patch on dmurdoch/manipulateWidget in the keepclass
branch, but it also includes the previous patch. I don't know how to submit a PR that only includes the new stuff.
This is a random question but seems related to how the package is grabbing rendered widgets and updating them. Is it possible to retrieve a rendered leaflet map? For example, I want to use code like manipulateWidget(leafletProxy("objectId"))
to return the same class of object as you get when a leaflet map is first created with leaflet()
. It seems simple, but is this possible?
Here is a more complete example:
# map created and saved
m1 <- leaflet() %>% addTiles()
# map rendered
output$mymap <- renderLeaflet({
leaflet() %>% addTiles()
})
# and then retrieved
m2 <- manipulateWidget(leafletProxy("mymap"))
# these are identical objects
identical(m1, m2)
When I use combineWidgets in manipulateWidget, if I change the size of the window, the widget won't resize.
I have two leaflet map widgets that i want to combine into a single widget, where i want both widgets height to be 95% of the vh
Specifying the height in combineWidgets to 200vh (for two widgets) works well, placing the maps one on top of the other where the user has to scroll down to the next map, but i want each map to be 95% height.
Right now the div style of each individual widget defaults to 100% and changing the height when creating the widget with leaflet does nothing to change the height when they are combined.
Is there a way to do this? Thanks.
Que doit-il se passer si on utilise combineWidgets sur une liste vide ? Erreur, warning ?
For instance, I could add a new parameter in manipulateWidget:
manipulateWidget(
...,
.return = function(finalWidget, envs) {finalWidget}
)
Ajouter un message d'erreur quand un input non partagé s'appuie sur un input partagé pour se mettre à jour.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.