Giter Site home page Giter Site logo

ggnet's Introduction

ggnet: network visualization with ggplot2

This repository contains the latest versions of the ggnet and ggnet2 functions, which allow to visualize networks as ggplot2 objects.

INSTALL

ggnet and ggnet2 are part of the GGally package. Install it from CRAN:

install.packages("GGally")

You can also install ggnet and ggnet2 as a small standalone package:

devtools::install_github("briatte/ggnet")

Note that you will need the latest version of ggplot2 (2.0.0) for any of the functions to work properly.

VIGNETTE

The ggnet2 function is fully documented in this vignette.

The data for one of the examples, a Twitter network of French Members of Parliament, is included in this repository, as is the vignette source.

THANKS

ggnet's People

Contributors

briatte 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

ggnet's Issues

Is the ggnet2 function available for use ?

Hi, sorry for bugging you with this minor problem. I couldn't use the ggnet2 function even after re-downloading the GGally package( ggnet works ). How can I fix this problem? Thanks beforehand!

Node placement

Is there a way to pre-specify placement of nodes? I would like to place one node at the center, and all the remaining nodes around it in a circle, and would like them to be placed in a pre-specified order.

Overlapping labels

Hello, I have just found this package and succesfully tried it. I think is a really nice solution within R and I will include this in my pipelines.

I would like to ask about whether we can control edges lengths and the overlapping of the labels in the nodes. My networks are nice but many nodes and labels are overlapping, so I have to make them really big in order to be able to differentiate them.

In my ggplot2 plots I've been using thepackage ggrepel to avoid overlapping labels, is there any kind of solution or can this package be used here too?

Thanks for your feedback

Error on first example in the tutorial

I'm trying to follow the examples here: https://briatte.github.io/ggnet/

And I'm getting this error:

Error: Each variable must be a 1d atomic vector or list.
Problem variables: 'x', 'y', 'xend', 'yend'

Is there something wrong with my environment? I tried starting clean, but I'm rather new to R.

The code I'm using:

> library(GGally)
> library(network)
> library(sna)
> library(ggplot2)
>
> # random graph
> net = rgraph(10, mode = "graph", tprob = 0.5)
> net = network(net, directed = FALSE)
> 
> # vertex names
> network.vertex.names(net) = letters[1:10]
> 
> ggnet2(net)
Loading required package: scales
Error: Each variable must be a 1d atomic vector or list.
Problem variables: 'x', 'y', 'xend', 'yend'

Can't set node size and group at the same time

Hi,

Seems like I can set node size and group separately but can't simultaneously. Here is the code

# make a graph
actors <- data.frame(name=c("Alice", "Bob", "Cecil", "David",
                            "Esmeralda"),
                     age=c(48,33,45,34,21),
                     gender=c("F","M","F","M","F"))
relations <- data.frame(from=c("Bob", "Cecil", "Cecil", "David",
                               "David", "Esmeralda"),
                        to=c("Alice", "Bob", "Alice", "Alice", "Bob", "Alice"),
                        same.dept=c(FALSE,FALSE,TRUE,FALSE,FALSE,TRUE),
                        friendship=c(4,5,5,2,1,1), advice=c(4,5,5,4,2,3))
g <- graph.data.frame(relations, directed=TRUE, vertices=actors)


# setting up node size alone works
ggnet(g, size=V(g)$age/2)

# setting up node group alone works as well
ggnet(g, node.group = V(g)$gender)

# this does NOT work if setting up size and group at the same time
ggnet(g, node.group = V(g)$gender, size = V(g)$age/2)

Thanks!

ggplot 3.3.4 required 'none' instead of FALSE in guides

Hey.
I am using ggnet and when plotting a graph I get the following warning:

4: The `<scale>` argument of `guides()` cannot be `FALSE`. Use "none" instead as of ggplot2 3.3.4.
i The deprecated feature was likely used in the ggnet package.
  Please report the issue at <https://github.com/briatte/ggnet/issues>.

So I obey and report (great verobse msg by the way!)

Thanks and wonderful work
image

Isolates appearing in graphs with all nodes of degree >= 30

I am plotting a network where nodes with degree of at least 30 have been preselected. Yet the plot shows several isolates. How can that be?

summary(r0_net %v% "degree")
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   30.0    38.0    52.0   403.8   493.0  4729.0 

  pdf(file="ggnet-ex.pdf")
  ggnet2(r0_net, color="color", size=2)
  dev.off()

ggnet-ex.pdf

adjust edge lengths

Hi, is there a way to adjust manually the distance between nodes?, I'm a bioinformatician and I would like to represent each node as a protein and the edge between proteins would be the similarity. Actually I only can plot the link between them but without any control on edges lengths.

thanks in advance

Read from network attributes

Some arguments for nodes, labels and possibly edges might be read from the network object attributes, as in this example that reads the mode.

Arguments that could be read from attributes:

  • weight.method (e.g. reading weighted centrality from the nodes)
  • node.group, node.alpha, node.color (would avoid problems when passing color scale values)
  • segment.alpha, segment.color and segment.size (using get.edge.attribute)
  • label.nodes and new arguments like label.color and label.alpha (yet to be added)

The issue is: how to distinguish network attribute names from colors?

Legend for edge.color

When I input a vector of color values for the edges, I cannot generate a legend which tells the reader what the colored edges represent. This would be a great enhancement.

No arrows when using ggnet2

Thanks for building this great package.

When I was trying to draw arrows in the network. No arrows are drawn. Any ideas why this happens?

Code:

library(plotly)
library(GGally)
library(network)
library(sna)
library(ggplot2)

p <- ggnet2(network(rgraph(10, tprob = 0.25), directed = TRUE),
       arrow.size = 12, arrow.gap = 0.025)

l <- plotly::ggplotly(p)

htmlwidgets::saveWidget(l, 'output.html')

newplot (13)

sessionInfo output is also attached as follows:

R version 4.0.2 (2020-06-22)
Platform: x86_64-conda_cos6-linux-gnu (64-bit)
Running under: CentOS Linux 7 (Core)

Matrix products: default
BLAS/LAPACK: xx/xxxx/xxxx/xxxx/

locale:
[1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
[3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
[5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
[7] LC_PAPER=en_US.UTF-8 LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C

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

other attached packages:
[1] sna_2.6 statnet.common_4.5.0 network_1.17.1
[4] GGally_2.1.2 plotly_4.9.3 ggplot2_3.3.5
[7] org.Mm.eg.db_3.12.0 AnnotationDbi_1.52.0 IRanges_2.24.1
[10] S4Vectors_0.28.1 Biobase_2.50.0 BiocGenerics_0.36.0
[13] clusterProfiler_3.18.1

loaded via a namespace (and not attached):
[1] enrichplot_1.10.0 bit64_4.0.5 RColorBrewer_1.1-2
[4] httr_1.4.2 tools_4.0.2 R6_2.5.0
[7] DBI_1.1.0 lazyeval_0.2.2 colorspace_2.0-0
[10] withr_2.4.1 tidyselect_1.1.0 gridExtra_2.3
[13] bit_4.0.4 compiler_4.0.2 scatterpie_0.1.5
[16] shadowtext_0.0.7 scales_1.1.1 stringr_1.4.0
[19] digest_0.6.27 DOSE_3.16.0 pkgconfig_2.0.3
[22] htmltools_0.5.1.1 fastmap_1.1.0 htmlwidgets_1.5.3
[25] rlang_0.4.10 RSQLite_2.2.5 farver_2.0.3
[28] generics_0.1.0 jsonlite_1.7.2 crosstalk_1.1.1
[31] BiocParallel_1.22.0 GOSemSim_2.16.1 dplyr_1.0.4
[34] magrittr_2.0.1 GO.db_3.12.1 Matrix_1.2-18
[37] Rcpp_1.0.6 munsell_0.5.0 viridis_0.5.1
[40] lifecycle_0.2.0 yaml_2.2.1 stringi_1.5.3
[43] ggraph_2.0.3 MASS_7.3-53 plyr_1.8.6
[46] qvalue_2.20.0 grid_4.0.2 blob_1.2.1
[49] ggrepel_0.9.1 DO.db_2.9 crayon_1.4.1
[52] lattice_0.20-41 graphlayouts_0.7.1 cowplot_1.1.1
[55] splines_4.0.2 pillar_1.4.7 fgsea_1.16.0
[58] igraph_1.2.6 reshape2_1.4.4 fastmatch_1.1-0
[61] glue_1.4.2 downloader_0.4 data.table_1.13.6
[64] BiocManager_1.30.10 vctrs_0.3.6 tweenr_1.0.1
[67] gtable_0.3.0 purrr_0.3.4 polyclip_1.10-0
[70] tidyr_1.1.2 reshape_0.8.8 assertthat_0.2.1
[73] cachem_1.0.3 ggforce_0.3.2 tidygraph_1.2.0
[76] coda_0.19-4 viridisLite_0.3.0 tibble_3.0.6
[79] rvcheck_0.1.8 memoise_2.0.0 ellipsis_0.3.1

Many thanks in advance.

Self-loop in ggnet

Hi! thank you for the amazing work. I was wondering if there is or there will be a plan for plotting self-loops!

Best,
D.

Error: ggnet2 cannot plot multiplex graphs

I can't find any info on what a multiplex graph is. Additional info on the help / io page would be useful, as my graph looks the same as all the ones on the io page. I'd like to know what is causing it to be classified as multiplex.

Better edges

Options that could improve weighted edges and directed graphs:

  • edge weights: the segment.size argument currently accepts a single value or a vector of values, but won't discover edge weights
  • edge labels: not implemented right now (although midpoints are computed as part of Moritz Marbach's original code)

Plotting geonetworks

I am not sure if an issue is the right way to ask this but I am trying to make a geographic network using ggplot2. I came across ggnet and it looks awesome. I saw that we need to provide as input the algorithm for laying out the graph to able to generate coordinates for nodes. But in case of a geographic network, I already have coordinates for my nodes. Is it possible to incorporate this information directly? Thanks.

layout.par\$seed.coord

Suggested by someone at R Addicts: it should be possible to set the seed of F-R force-directed graphs (see there), which should in turn allow to plot successive networks for each month or so, and plot a dynamic network visualization.

Options for setting vertex attribute for grouping

Are there more options to set the vertex attribute for grouping, except by using the ifelse argument?

net %v% "phono" = ifelse(letters[1:10] %in% c("a", "e", "i"), "vowel", "consonant")

I want to group character vectors that indicate the nodes in the network, but cannot figure out how to do it.

Does not plot due to error "cannot find arrow() function"

Dear François,

thank you for the really nice network plotting function. Unfortunately the code broke during one of the last commits so that plotting does not work anymore. The following example is taken from the examples listed in the ggnet2 documentation and produces the error:

start R
library(ggnet)

x <- 10
ndyads <- x * (x - 1)
density <- x / ndyads
m <- matrix(0, nrow = x, ncol = x)
dimnames(m) <- list(letters[ 1:x ], letters[ 1:x ])
m[ row(m) != col(m) ] <- runif(ndyads) < density
m

random undirected network

n <- network::network(m, directed = FALSE)
n

ggnet2(n, label = TRUE)

I cloned your repository, fixed this and other problems and will submit a pull request.

Best,
Christoph

Moving node labels

Hello,
is there an option to move node labels from the center of the node?
I'd like to put them under the nodes because my labels are too big!
Thank you!

large network

When I tried plot a network I receive this error "Removed 509 rows containing missing values (geom_segment). "
I dont know what the problem is, the lines and collumns colapsed in the same edges and others lists are created. in same matrices I cannot have this error.
sorry if is my bad, i can't find a solution.
image

Legend Title

I am probably missing something obvious, but is is possible to remove the legend title and just show the legend values when using the parameter color?

For context, I was thinking something along the lines of

ggnet2(g, 
       color = "ntype", 
       palette = col, 
       mode = "fruchtermanreingold", 
       alpha=.7, 
       legend.position = "bottom", 
       legend.title=element_blank())

ggnet2: argument `arrow.gap` introduces shifting of the edges

Network plot without arrows:

net = network(rgraph(10, tprob = 0.25), directed = TRUE)
ggnet2(net)

image
After adding arrows with arrow.size:

ggnet2(net, arrow.size = 20)

image
Observe shifting of the edges or similar questionable effect after adding arrow.gap only:

ggnet2(net, arrow.size = 20, arrow.gap = 0.05)

image

Running with GGally 1.0.1, ggplot2 2.1.0, grid 3.4.0

hover text

I am finding it incredibly difficult to customize the hover text information when combining ggnet2 with ggplotly. I was able to use the 'text' parameter and then add custom text as follows:
ggplotly(p,hoverinfo='text') %>% style(hovertext = 'specialty')
I can add a list to the hovertext parameter, but it only takes the first element in the list. I can specify any element in the list (list[x]) and it will move to the xth element in the list, which tells me that the package is reading in the list. I'm fairly certain that the length of the list is equal to the number of nodes in the graph. Any help would be appreciated.

Error in vignette_Example (4): French MPs on Twitter

when I run :
ggnet2(net, color = "party", palette = y, alpha = 0.75, size = 4, edge.alpha = 0.5)

Error in geom_point():
! Problem while converting geom to grob.
ℹ Error occurred in the 2nd layer.
Caused by error:
! Unknown colour name: UMP
Backtrace:

  1. base (local) <fn>(x)
  2. ggplot2:::print.ggplot(x)
  3. ggplot2:::ggplot_gtable.ggplot_built(data)
  4. ggplot2:::by_layer(...)
  5. ggplot2 (local) f(l = layers[[i]], d = data[[i]])
    ...
  6. self$draw_panel(data, panel_params, coord, na.rm = FALSE)
  7. ggplot2 (local) draw_panel(..., self = self)
  8. scales::alpha(coords$colour, coords$alpha)
  9. farver::decode_colour(colour, alpha = TRUE)
  10. farver:::decode_c(...)

Manual weighting?

Is there a way, or would you consider adding a way, to set the weighting manually?

I'm trying to construct a network for twitter users who discuss a particular topic. I'd like to weight each node by the number of people who would see a broadcast from that node. In twitter-speak, that's the number of "followers." I could populate my graph with an edge for every follower. Then it would have 75,000 edges instead of 300, which would create a nasty subsetting problem. So instead I only keep data for edges between users who've commented on the topic, and I track each user's number of followers.

Make sense?

fixing coordinates of vertices

I am plotting the same network (consisting of identical node and edge sets), with different node colorings to show different structure. Each plot assigns the nodes different coordinates on the figure; I'd like to make the coordinates the same, so that a reader sees to identical pictures in terms of the node and edges, but different colorings of the same. In the gplot function in the sna package, coordinates can be fixed using the coord argument. Is there a way to fix coordinates in ggnet?

For an example, see the bottom two figures at http://rpubs.com/khanna7/186429. I'd like the two networks to look the same, aside from the node features that are highlighted.

node.group is not correct after setting subset.threshold

Hi,
after setting the subset.threshold, the group of the nodes seem not correct, here is the code I tested:
n= network(35,directed=FALSE)
type <- sample(1:2, 35, replace=T)
names(type) <- seq(1,35)
ggnet(n,node.group=type,label.nodes = TRUE,subset.threshold =0)
ggnet(n,node.group=type,label.nodes = TRUE,subset.threshold =2)

the group is:
screen shot 2015-08-27 at 10 52 49 am

this is the result and the color of some nodes are not correct such as 8, 10, 18 :
screen shot 2015-08-27 at 10 51 18 am
screen shot 2015-08-27 at 10 47 43 am

Restriction on Edge Labels

Edge labels are centered. Not possible to enter 2 edge labels on the same arrow.
This is needed:
For example, in Network Topology of causal relationships in a VAR model, it is customary to write the p values of the G-causalities on the same arrow; one is to indicate the GC from variable A to variable B, and the other is from variable B to variable A.

It seemed impossible to me to construct such a needed graph with ggnet.

Example (the graphs to be drawn Needed, but not Possible with ggnet)
Figure 3 here: https://www.academia.edu/17057780/Determinants_of_Current_Account_Deficit_in_Turkey_The_Conditional_and_Partial_Granger_Causality_Approach

Note that 2 labels are needed (one at the beginning and the other at the end of the same arrow).

Add weights in correct order of edge list

Hi, when supplying a data.frame object of directed node edge lists, I would then like to highlight the size of the edges by a certain weight. The tutorial shows how one can add a variable representing the edge weights, but I am unable to add them in the right order (realized this when I noticed the order did not match the variable that was in the data.frame). Is there a way to ensure this?

dat <- data.frame("Item"=sample(letters[1:10],5),"Event"=sample(1:10,5),weight=runif(sample(1:4,5)))

net <- network(dat,
               directed = TRUE,
               matrix.type="edgelist")

set.edge.value(x = net,attrname = "weight",value = dat$weight)

all.equal(dat$weight,net %e% "weight") # Returns FALSE, leading to incorrect weights being used for edge thickness.

How can I ensure the order in the net object matches that of the data,.frame, so that I can also add other variables (e.g. color specifications for arrows) to match the right edge lists?.

could not find function "arrow"

Why am I getting this error?

net = rgraph(10, mode = "graph", tprob = 0.5)
net = network(net, directed = FALSE)
network.vertex.names(net) = letters[1:10]
ggnet(net)
Error in do.call("layer", list(mapping = mapping, data = data, stat = stat, :
could not find function "arrow"

vertex color custom palette w/ 1 level

When the vertex attribute V(net)$color has only 1 unique label (="Mixed"), then

ggnet2(net, color="color", palette="Set1")

works fine but

ggnet2(net, color="color", palette=custom_palette)

does not:

Error in grDevices::col2rgb(colour, TRUE) : invalid color name 'Mixed'

The workaround

ggnet2(net, color = custom_palette[V(net)$Direction])

does the trick but does not plot a legend.

This behavior is unexpected to me. Maybe you can provide help or a fix.

Thanks in advance & best regards

Michael.

bipartite plotting issue

The bipartite network plotting seems to fail in the following example. When the number of rows exceeds the number of columns it does work. I am not sure if this is an inherent technical limitation of bipartite graphs here. If it is, the function could provide at least an informative error message.

x <- matrix(rgamma(8*8, shape = 1), nrow = 8, ncol = 8); bip <- network::network(x, matrix.type = "bipartite"); p <- ggnet2(bip); print(p)

This produces an error:
Error in data.frame(..., check.names = FALSE) :
arguments imply differing number of rows: 16, 8

Error in vignette: 1d atomic vector or list

I've tried to run the first few lines of the ggnet2 vignette when I can an error stating that Each variable must be a 1d atomic vector or list. I'm not clear on what this is referencing. I can generated the net variable

net = rgraph(10, mode = "graph", tprob = 0.5)
net = network(net, directed = FALSE)

# vertex names
network.vertex.names(net) = letters[1:10]

which ends up being this

>net
 Network attributes:
  vertices = 10 
  directed = FALSE 
  hyper = FALSE 
  loops = FALSE 
  multiple = FALSE 
  bipartite = FALSE 
  total edges= 28 
    missing edges= 0 
    non-missing edges= 28 

 Vertex attribute names: 
    vertex.names 

No edge attributes

However, when I try to run..

ggnet2(net)

I get an error Error: Each variable must be a 1d atomic vector or list. Problem variables: 'x', 'y', 'xend', 'yend'

I haven't been able to track down a reason for this error or why it is arising from the vignette. I have ggplot v. 2.2.1, GGally 1.3.0, both sna2.4 and network 1.13, and scales 0.4.1.

Any insights into what I might be missing would be appreciated.

ColorBrewer palette problems

Hello,

I've been using ggnet2 to make network plots from igraph-generated networks. I've done this by using

gr <- as_data_frame(ig, what = "both")

, then using ggnet2 to plot from the resulting dataframes. In general, this works very well. But I'm having some trouble setting color palettes.

This works:

ggnet2(gr$edges, node.color = gr$vertices$Kingdom, palette = "Set1")

But this doesn't work:

ggnet2(gr$edges, node.color = gr$vertices$Kingdom, palette = brewer.pal(10, "Set1"))

And neither does defining a color palette separately, then referring to it with the ggnet2 function.

I get an error like this:

Error in grDevices::col2rgb(colour, TRUE) : 
  invalid color name 'FUNGI'

So I seem to be limited to the number of colors provided in the default colour brewer palettes. Which isn't ideal. Why does this happen?

Andrew.

ggnet2 does not show Chinese characters

Hi, I am new to ggnet2. I was working on a token network analysis. I realized that ggnet2 does not show Chinese tokens at all (see the screenshot please). How do I fix it? Any solutions are appreciated!

Screenshot 2023-03-20 at 10 26 33 AM

bipartite

thanks François!
It would be great to have specific functions to handle bipartite networks. With the exception of the bipartite package most existing R packages do not include simple ways to plot bipartite structures.
I'd suggest a quick way to code the two modes of the bipartite network, with distinct shape/colour combinations for instance.

Error: shared object ‘stringi.so’ not found

devtools::install_github("briatte/ggnet")
#> Downloading GitHub repo briatte/ggnet@master
#> Error in library.dynam(lib, package, package.lib) :
#>   shared object ‘stringi.so’ not found

devtools::session_info()
#> Session info -------------------------------------------------------------------
#>  setting  value
#>  version  R version 3.2.2 (2015-08-14)
#>  system   x86_64, linux-gnu
 #> ui       X11
 #> language (EN)
 #> collate  en_US.UTF-8
#>  tz       <NA>
#>  date     2015-11-03
#> 
#> Packages -----------------------------------------------------------------------
 #> package  * version date       source
 #> devtools   1.9.1   2015-09-11 CRAN (R 3.2.2)
 #> digest     0.6.8   2014-12-31 CRAN (R 3.2.2)
#>  memoise    0.2.1   2014-04-22 CRAN (R 3.1.1)

arranging plots in a grid

Hello,

I have used 'ggnet' to show the evolution of the networks of two nodes over three waves here: http://rpubs.com/khanna7/183807

I am looking for ideas on how to arrange these nicely in a grid. If you have some ideas, please let me know.

Thank you,
Aditya Khanna

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.