Giter Site home page Giter Site logo

daattali / ggextra Goto Github PK

View Code? Open in Web Editor NEW
379.0 18.0 48.0 2.16 MB

📊 Add marginal histograms to ggplot2, and more ggplot2 enhancements

Home Page: http://daattali.com/shiny/ggExtra-ggMarginal-demo/

License: Other

R 94.48% CSS 2.75% Makefile 2.77%
r rstats ggplot2 ggplot2-enhancements r-package marginal-plots

ggextra's Introduction

ggExtra - Add marginal histograms to ggplot2, and more ggplot2 enhancements

CRAN version CI build

Copyright 2016 Dean Attali. Licensed under the MIT license.

ggExtra is a collection of functions and layers to enhance ggplot2. The flagship function is ggMarginal, which can be used to add marginal histograms/boxplots/density plots to ggplot2 scatterplots. You can view a live interactive demo to test it out!

Most other functions/layers are quite simple but are useful because they are fairly common ggplot2 operations that are a bit verbose.

This is an instructional document, but I also wrote a blog post about the reasoning behind and development of this package.

Note: it was brought to my attention that several years ago there was a different package called ggExtra, by Baptiste (the author of gridExtra). That old ggExtra package was deleted in 2011 (two years before I even knew what R is!), and this package has nothing to do with the old one.

Installation

ggExtra is available through both CRAN and GitHub.

To install the CRAN version:

install.packages("ggExtra")

To install the latest development version from GitHub:

install.packages("devtools")
devtools::install_github("daattali/ggExtra")

Marginal plots RStudio addin/gadget

ggExtra comes with an addin for ggMarginal(), which lets you interactively add marginal plots to a scatter plot. To use it, simply highlight the code for a ggplot2 plot in your script, and select ggplot2 Marginal Plots from the RStudio Addins menu. Alternatively, you can call the addin directly by calling ggMarginalGadget(plot) with a ggplot2 plot.

ggMarginal gadget screenshot

Usage

We’ll first load the package and ggplot2, and then see how all the functions work.

library("ggExtra")
library("ggplot2")

ggMarginal - Add marginal histograms/boxplots/density plots to ggplot2 scatterplots

ggMarginal() is an easy drop-in solution for adding marginal density plots/histograms/boxplots to a ggplot2 scatterplot. The easiest way to use it is by simply passing it a ggplot2 scatter plot, and ggMarginal() will add the marginal plots.

As a simple first example, let’s create a dataset with 500 points where the x values are normally distributed and the y values are uniformly distributed, and plot a simple ggplot2 scatterplot.

set.seed(30)
df1 <- data.frame(x = rnorm(500, 50, 10), y = runif(500, 0, 50))
p1 <- ggplot(df1, aes(x, y)) + geom_point() + theme_bw()
p1

And now to add marginal density plots:

ggMarginal(p1)

That was easy. Notice how the syntax does not follow the standard ggplot2 syntax - you don’t “add” a ggMarginal layer with p1 + ggMarginal(), but rather ggMarginal takes the object as an argument and returns a different object. This means that you can use magrittr pipes, for example p1 %>% ggMarginal().

Let’s make the text a bit larger to make it easier to see.

ggMarginal(p1 + theme_bw(30) + ylab("Two\nlines"))

Notice how the marginal plots occupy the correct space; even when the main plot’s points are pushed to the right because of larger text or longer axis labels, the marginal plots automatically adjust.

If your scatterplot has a factor variable mapping to a colour (ie. points in the scatterplot are colour-coded according to a variable in the data, by using aes(colour = ...)), then you can use groupColour = TRUE and/or groupFill = TRUE to reflect these groupings in the marginal plots. The result is multiple marginal plots, one for each colour group of points. Here’s an example using the iris dataset.

piris <- ggplot(iris, aes(Sepal.Length, Sepal.Width, colour = Species)) +
  geom_point()
ggMarginal(piris, groupColour = TRUE, groupFill = TRUE)

You can also show histograms instead.

ggMarginal(p1, type = "histogram")

There are several more parameters, here is an example with a few more being used. Note that you can use any parameters that the geom_XXX() layers accept, such as col and fill, and they will be passed to these layers.

ggMarginal(p1, margins = "x", size = 2, type = "histogram",
           col = "blue", fill = "orange")

In the above example, size = 2 means that the main scatterplot should occupy twice as much height/width as the margin plots (default is 5). The col and fill parameters are simply passed to the ggplot layer for both margin plots.

If you want to specify some parameter for only one of the marginal plots, you can use the xparams or yparams parameters, like this:

ggMarginal(p1, type = "histogram", xparams = list(binwidth = 1, fill = "orange"))

Last but not least - you can also save the output from ggMarginal() and display it later. (This may sound trivial, but it was not an easy problem to solve - see this discussion).

p <- ggMarginal(p1)
p

You can also create marginal box plots and violin plots. For more information, see ?ggExtra::ggMarginal.

Using ggMarginal() in R Notebooks or Rmarkdown

If you try including a ggMarginal() plot inside an R Notebook or Rmarkdown code chunk, you’ll notice that the plot doesn’t get output. In order to get a ggMarginal() to show up in an these contexts, you need to save the ggMarginal plot as a variable in one code chunk, and explicitly print it using the grid package in another chunk, like this:

```{r}
library(ggplot2)
library(ggExtra)
p <- ggplot(mtcars, aes(wt, mpg)) + geom_point()
p <- ggMarginal(p)
```
```{r}
grid::grid.newpage()
grid::grid.draw(p)
```

removeGrid - Remove grid lines from ggplot2

This is just a convenience function to save a bit of typing and memorization. Minor grid lines are always removed, and the major x or y grid lines can be removed as well (default is to remove both).

removeGridX is a shortcut for removeGrid(x = TRUE, y = FALSE), and removeGridY is similarly a shortcut for… .

df2 <- data.frame(x = 1:50, y = 1:50)
p2 <- ggplot2::ggplot(df2, ggplot2::aes(x, y)) + ggplot2::geom_point()
p2 + removeGrid()

For more information, see ?ggExtra::removeGrid.

rotateTextX - Rotate x axis labels

Often times it is useful to rotate the x axis labels to be vertical if there are too many labels and they overlap. This function accomplishes that and ensures the labels are horizontally centered relative to the tick line.

df3 <- data.frame(x = paste("Letter", LETTERS, sep = "_"),
                  y = seq_along(LETTERS))
p3 <- ggplot2::ggplot(df3, ggplot2::aes(x, y)) + ggplot2::geom_point()
p3 + rotateTextX()

For more information, see ?ggExtra::rotateTextX.

plotCount - Plot count data with ggplot2

This is a convenience function to quickly plot a bar plot of count (frequency) data. The input must be either a frequency table (obtained with base::table) or a data.frame with 2 columns where the first column contains the values and the second column contains the counts.

An example using a table:

plotCount(table(infert$education))

An example using a data.frame:

df4 <- data.frame("vehicle" = c("bicycle", "car", "unicycle", "Boeing747"),
                  "NumWheels" = c(2, 4, 1, 16))
plotCount(df4) + removeGridX()

For more information, see ?ggExtra::plotCount.

ggextra's People

Contributors

alanocallaghan avatar crew102 avatar daattali avatar indrajeetpatil avatar seasmith avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ggextra's Issues

Notes suggested by @baptiste

as suggested by @baptiste

  1. See if the hacks caused by gridExtra not playing nicely in packages can be removed
  2. add a note about the fact that this is not the same ggExtra as the one from many years ago

ggMarginal: when main plot is using log/sqrt/etc scale, marginal plots should also

This isn't trivial because I don't know how to generalize looking for the current scale on a plot and using the same scale on another plot. I can manually check "is there a log x/y scale? if so, then add a log x/y scale to the margin plots" and repeat that for every common transformation. But not sure yet how to do it efficiently.

library(ggplot2)
library(ggExtra)
set.seed(123)
df <- data.frame(x = rlnorm(100), y = rlnorm(100))

p1 <- ggplot(df, aes(x, y)) + geom_point() + scale_x_log10() + scale_y_log10()
ggMarginal(p1, type = "histogram")

horizontal geoms

would you be interested in a contribution (pull request) of some horizontal variants of geoms such as linerange (useful when trying to use faceting and flipped coordinates together, which is not currently feasible in ggplot2)?

e.g. see:

Add marginal density/histogram to geom_hex

It will be nice to able to show geom_hex along with two densities on top and right since there are circumstances where scatterplot is too slow due to the huge number of events.

Histograms axes limits are wrong when using geom_smooth()

Occasionally, I like to have both axes of a scatter have the same range or limits (in the original plot below I set the limits to c(-20,30)). However, to demonstrate the issue, I changed the y-axis limits using scale_y_continuous(limits = c(-40,30)) while having scale_x_continuous(limits = c(-20,30)).

The actual range of the data in the x-axis is: -17.49, 28.56 and on the y-axis is: -9.63, 17.58

I think the location of histograms should adjust and shift when the axes limits are shifted.

ggextra-issue

Add support for dotplots

There was a blog post showing how to do many Tufte-style plots in R. The author included ggMarginal but noted that it cannot be used to make dotplots eg

I suppose it could be a nice extra feature to support those kind of plots as well, even though they're very very similar to histograms. I looked into it very briefly and unfortunately the ggplot2::geom_dotplot() doesn't seem to work because when there are many observations the dots go off the screen. There might be a way to somehow dynamically decide how big to make the dots. There can also be other solutions (perhaps useful resource: http://lenkiefer.com/2016/04/06/dot-plots-and-distributions)

If anybody wants to tackle this, feel free to make a PR!

Initial questions

Hi there -

Two initial questions I have come across while refactoring:

  1. Are we sure that this is needed for ggplot2 V 2.2 and above (lines 96-99 of ggMarginal.R):
 # after ggplot2 v1.0.1, layers became strict about parameters
  if (type == "density") {
    extraParams[['fill']] <- NULL
}

I'm getting the behavior that I would want (a warning from ggplot: "Warning: Ignoring unknown parameters: fill") when I drop those lines from ggMarginal and I run this code:

p <- ggplot2::ggplot(mtcars, ggplot2::aes(wt, mpg)) + ggplot2::geom_point()
ggExtra::ggMarginal(p, type = "density", fill = "black")

I also don't understand why this line would be needed for a density geom and not boxplot/histogram but that's probably just my ignorance.

  1. Regarding this bit of code (lines 113-143 of ggMarginal.R):
if (missing(p)) {
    if (missing(data) || missing(x) || missing(y)) {
      stop("`data`, `x`, and `y` must be provided if `p` is not provided",
           call. = FALSE)
    }
    p <- ggplot2::ggplot(data, ggplot2::aes_string(x, y)) + ggplot2::geom_point()
    x <- as.symbol(x)
    y <- as.symbol(y)
  } else {
    if (missing(data)) {
      if (methods::is(p$data, "waiver")) {
        stop("`data` must be provided if it is not part of the main ggplot object",
             call. = FALSE)
      }
      data <- p$data
    }
    if (length(p$mapping) == 0) p$mapping <- p$layers[[1]]$mapping
    if (margins != "y" && missing(x)) {
      if (is.null(p$mapping$x)) {
        stop("`x` must be provided if it is not an aesthetic of the main ggplot object",
             call. = FALSE)
      }
      x <- p$mapping$x
    }
    if (margins != "x" && missing(y)) {
      if (is.null(p$mapping$y)) {
        stop("`y` must be provided if it is not an aesthetic of the main ggplot object",
             call. = FALSE)
      }
      y <- p$mapping$y
    }
  }

...We already make sure in the if statement that the user provided data, x, and y if they didn't provide p. Under what circumstance could they pass this test and be thrown an error in the else block? In other words, under what circumstances would the user supply a ggplot object p but you still need them to supply x, y, or data? It looks like it may be an assertion that you ggplot still keeps x, y, and data where you think they will be in the plot object, but it's hard to tell if you're testing that or user params.

Histogram margin should be inside of legend

Minimal example:

library("ggExtra")
# Create some data
set.seed(1234)
x <- c(rnorm(500, mean = -1), rnorm(500, mean = 1.5))
y <- c(rnorm(500, mean = 1), rnorm(500, mean = 1.7))
col <- c(rnorm(500, mean = 1), rnorm(500, mean = 1.3))
df3 <- data.frame(x, y, col)
# Scatter plot of x and y variables and color by groups
sp2 <- ggplot(df3,aes(x, y, color=col)) + geom_point()
ggMarginal(sp2 + theme_gray(), type="histogram")

image

The legend and the y-axis histogram should be switched.

`Error: no layers in the plot` still occures for gridExtra_0.9.1

Error: no layers in the plot still occures when you have an old version of gridExtra (it does not work for me for version gridExtra_0.9.1) so you should ensure that user has at least version 2.0.0 of gridExtra. Can you fix this somehow or add it to the vignette/info/description?

ggMarginal(p) invalidates the boldness of the main plot title

ggMargin is great. But it changes bold main title to plain text, which is not desired.

p <- ggplot(mtcars, aes(x=wt, y=mpg)) + geom_point() + theme_bw() +
labs(title="Main Title", y="MPG") +
theme(plot.title=element_text(face="bold", size=14),
axis.title.y=element_text(face="bold", size=14))

p's main title and y are bold.

ggMarginal(p, margins="y", size=4)

Now main title is changed to plain text. The y title font face is not affected. Can you maintain the font face of main title?

Adding marginal plots for grouped data

Hi Dean,

Thank you for your work in ggExtra package, which makes it really easy to add marginal plots to ggplots.

It would be highly appreciated, if one can add marginal plots for grouped data as illustrated here and here

Suggestion: Improve ggMarginal()so that it reacts to the mapping arguments.

sp <- ggplot(iris, aes(Sepal.Length, Sepal.Width))+
  geom_point(aes(color = Species))

ggMarginal(sp, data = iris, mapping = aes(color = Species) )

scatter-plot-and-correlation-marginal-plot-grouped-data-1

Best regards,

Remove external border when combining several graphs

Hi,

I couldn't find the way not to plot the outer frame when combining graphs through ggplot2 + ggExtra + cowplot. I am not sure where I have to tell R, but suspect the issue to lie in ggExtra. Here is an example:
require(ggplot2)
require(cowplot)
require(ggExtra)

Creat a graph

A <- ggplot(mpg, aes(x = cty, y = hwy, colour = factor(cyl))) + geom_point(size = 2.5)

Add marginal histogram

B <- ggExtra::ggMarginal(A,type = 'histogram', margins = 'x', size = 9)

Combine through cowplot

combo <- plot_grid(B,B,labels=c("A","B"))
plot(combo) # looks fine

Re-combine through cowplot

plot_grid(B,combo,ncol=1,rel_heights = c(2,3))

The question is also posted on Stackoverflow, here.

Thanks for any help!

ggMarginal can’t handle Date axes

library(ggExtra)
data(airquality)
airquality$Date <- with(airquality, as.Date(sprintf('1973-%02d-%02d', Month, Day)))

p <- ggplot(airquality, aes(Date, Temp)) + geom_point()
print(ggMarginal(data = airquality, x = 'Date', y = 'Temp'))  # works
print(ggMarginal(p, airquality, 'Date'))                      # doesn’t

the second one throws:

Error: Invalid input: date_trans works with objects of class Date only
Traceback:

1. print(ggMarginal(p, airquality, "Date"))
2. ggMarginal(p, airquality, "Date")
3. ggplot2::ggplot_build(top)
4. lapply(data, scales_transform_df, scales = scales)
5. FUN(X[[i]], ...)
6. unlist(lapply(scales$scales, function(s) s$transform_df(df = df)), 
 .     recursive = FALSE)
7. lapply(scales$scales, function(s) s$transform_df(df = df))
8. FUN(X[[i]], ...)
9. s$transform_df(df = df)
10. f(..., self = self)
11. lapply(df[aesthetics], self$transform)
12. FUN(X[[i]], ...)
13. f(..., self = self)
14. self$trans$transform(x)
15. stop("Invalid input: date_trans works with objects of class Date only", 
  .     call. = FALSE)

Should ggMarginal suppress warnings when type = boxplot or density

Depending on the type of marginal plot, ggMarginal will pass along one of these warnings:

  1. type = histogram - i.e., ggMarginal(data = mtcars, x = "mpg", y = "wt", type = "histogram")
`stat_bin()` using `bins = 30`.
Pick better value with
`binwidth`.
  1. type = boxplot - i.e., ggMarginal(data = mtcars, x = "mpg", y = "wt", type = "boxplot")
Warning messages:
1: Continuous x aesthetic -- did you forget aes(group=...)? 
2: Continuous x aesthetic -- did you forget aes(group=...)? 
3: Continuous x aesthetic -- did you forget aes(group=...)? 
  1. type = density - i.e., ggMarginal(data = mtcars, x = "mpg", y = "wt", type = "density")
Warning: Ignoring unknown parameters: fill
Warning: Ignoring unknown parameters: fill

In my opinion we should only pass along the warning in case number 1 (i.e., the binwidth warning when type = histogram). The other two warnings are not helpful and are the result of expected behavior. What do you think - should we suppress these warnings?

legends offsets histograms

Hi,
when you have legends, the marginal plots are not displayed correctly to the axis. See the attached files for an example.
Regards,
Yadhu

without legend
withlegend

ggMarginal should carry theme of title through

Right now ggMarginal only carries the color and font face of the scatter plot's title through to the final plot. The text grob that we use for a title in the final plot is created here:

    title <- grid::textGrob(
      pb$plot$labels$title,
      gp = grid::gpar(col = pb$plot$theme$plot.title$colour,
                      fontsize = 16, fontface = pb$plot$theme$plot.title$face)
    )

It's easy to pull out the ggplot2 titleGrob that contains all of the theme elements desired by the user, and drop that grob in instead of using grid::textGrob. I will include this in the next PR.

Error shiny

With the upgrade of shiny says "No layers in plot" which should be the graph:

When plotting marginal histograms, the first and last bin are sometimes cut off

As reported by a user in a private email, the first and last bins seem to be cut off. I'm suspecting it's because the first bin's left edge is actually outside of the range of the main plot. For example, if the main scatterplot begins at x = 10, then maybe the first bin is centered at x = 10, but its left edge is at x = 9, which is not within the range.

Add arguments to 'rotateTextX()'

It would add more convenience to an already convenient function. An idea:

rotateTextX <- function (angle = 90, hjust = angle/90, vjust = 0.5) 
{
  ggplot2::theme(
    axis.text.x = ggplot2::element_text(angle = angle, hjust = hjust, vjust = vjust)
  )
}

Hi. I am having a lot of trouble getting this to work. First, the grid package isn't available for the R version I have (latest) and then even though the package is loaded, I get a msg saying to '...please install gridExtra' What am I missing?

Hi. I am having a lot of trouble installing gridExtra. First, grid doesn't install under the current version of R and then when I try running running the package I get "Error: gridExtra package is required for this function to work. Please install it." even though the package is installed. Help?

ggMarginal() not working with ggplot2.2.1.900

I am trying to replicate the example:


library("ggplot2")
library("ggExtra")

set.seed(30)
df <- data.frame(x = rnorm(500, 50, 10), y = runif(500, 0, 50))
p <- ggplot(df, aes(x, y)) + geom_point()

ggMarginal(p)

Which results the following error:

Error: Don't know how to add o to a plot
In addition: Warning message:
In mean.default(getLimits(pbTop, "y")) :
argument is not numeric or logical: returning NA


Session info:

R version 3.3.2 (2016-10-31)
Platform: x86_64-apple-darwin13.4.0 (64-bit)
Running under: macOS Sierra 10.12.3

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] ggExtra_0.6.1      ggplot2_2.2.1.9000

loaded via a namespace (and not attached):
 [1] Rcpp_0.12.9      digest_0.6.12    assertthat_0.1   mime_0.5         grid_3.3.2      
 [6] plyr_1.8.4       R6_2.2.0         xtable_1.8-2     gtable_0.2.0     scales_0.4.1    
[11] lazyeval_0.2.0   miniUI_0.1.1     labeling_0.3     tools_3.3.2      munsell_0.4.3   
[16] shiny_1.0.0.9000 httpuv_1.3.3     colorspace_1.3-2 htmltools_0.3.5  tibble_1.2 

Adding axis to marginal denstity plot and histograms

Great package, anyway I think it could be useful to have the possibility to show the axis of the density plot/histogram, in order to be able to compare distributions of subsets of data (see pict):

example_1

As you can see the maximum of each the density distribution is the same, therefore it's not possible to appreciate the differences in density value.
Thanks in advance.
Sebastiano

Estrange behaviour: ggMarginal (p1, type = "histogram")

Dear @daattali,

I am using ggExtra on a shiny app. I dont know why, but today the rendered plot changed and the histogram is now a "rug" like plot. Any advise on that?

See below a small reproducible example.

library(ggplot2); library(ggExtra)
set.seed(30)
df1 <- data.frame(x = rnorm(500, 50, 10), y = runif(500, 0, 50))
(p1 <- ggplot(df1, aes(x, y)) + geom_point() + theme_bw())

ggMarginal(p1, type = "histogram")
#> Scale for 'x' is already present. Adding another scale for 'x', which
#> will replace the existing scale.

On smaller monitors, results plot is "cut-off" at bottom x-axis.

NOTE: Problem only happens on smaller monitors.
My 2nd monitor, where I run R studio, is 14 inches diag.
(No problem on larger monitors)

Using your great mtcars ggExtra Margins example,
in the latest Rstudio / Linux.

From the Console panel,
this works ok:

library(ggplot2)
library(ggExtra)
myplot <- ggplot(mtcars, aes(wt, mpg)) + geom_point()

But...using the Rstudio "addin"
from the Code panel,
shows:
http://imgur.com/epvDELb

See?
The bottom part of the plot is "cut-off" (below mpg=10)
...can not see the wt x-axis.

So yes, everybody with smaller monitors
may have that problem.

Q: (possible solution?)
Is there a way
to make the results Margins popup window,
"user-resizable"?.

I'm sure that if I could use the mouse
to "resize" that popup,
the hidden parts will re-appear OK,
even on smaller monitors.

btw:
There is lots of unused screen space
around that popup,
so allowing the user to mouse-resize it,
would certainly solve the problem! :-)

Error running ggMarginal

First, thank you very much for developing such a nice package!

I am having this error when running the function 'ggMarginal'

Error in data.frame(x = .Primitive("log10"), PANEL = c(1L, 1L, 1L, 1L, :
arguments imply differing number of rows

Any idea how to solve the problem?

Maybe this is related to the log10 in the formula in ggplot2.

The code used:

p1 <- ggplot(dat.crop, aes(y = log10(AGr), x = log10(herb + 1))) +
geom_point(size = 3, color = "tomato")+
geom_smooth(method = "lm")
ggMarginal(p1, type = "histogram")

Thanks in advance

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.