You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将R数据框转换为适配d3.hierarchy的JSON列表结构并构建篮球树形对阵图

Solution: Build a Binary Bracket Tree with D3.js from R Basketball Data

Let's split this into two core tasks: converting your R data frame to the proper nested JSON structure for d3.hierarchy, then implementing the bracket visualization with D3.

1. Convert R Data Frame to Binary Tree JSON

First, we need to transform your flat basketball data into a nested structure where every non-leaf node has exactly two children. Let's start with a sample data frame (adjust this to match your actual data):

# Sample basketball bracket data
bracket_df <- data.frame(
  id = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15),
  name = c("Final", "Semifinal 1", "Semifinal 2", "Quarterfinal 1", "Quarterfinal 2", 
           "Quarterfinal 3", "Quarterfinal 4", "Team A", "Team B", "Team C", "Team D", 
           "Team E", "Team F", "Team G", "Team H"),
  parent_id = c(NA, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7),
  is_leaf = c(FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE)
)

Next, we'll write a recursive function to build the nested list structure required for d3.hierarchy:

library(jsonlite)

build_binary_tree <- function(df, parent_id = NA) {
  # Get all nodes for the current parent
  current_nodes <- df[df$parent_id == parent_id, ]
  
  # If no nodes, return NULL
  if(nrow(current_nodes) == 0) return(NULL)
  
  # For non-leaf nodes, we need exactly two children
  tree_list <- lapply(1:nrow(current_nodes), function(i) {
    node <- current_nodes[i, ]
    list(
      name = node$name,
      children = if(!node$is_leaf) {
        # Recursively build children for non-leaf nodes
        build_binary_tree(df, parent_id = node$id)
      } else {
        NULL # Leaf nodes have no children
      }
    )
  })
  
  # Ensure non-root nodes have exactly two children (adjust if your data has gaps)
  if(!is.na(parent_id) && length(tree_list) != 2) {
    stop("Non-leaf nodes must have exactly two children!")
  }
  
  tree_list
}

# Build the root tree (parent_id = NA is the root node)
bracket_tree <- build_binary_tree(bracket_df)

# Convert to JSON (this is what we'll pass to D3)
bracket_json <- toJSON(bracket_tree[[1]], auto_unbox = TRUE, pretty = TRUE)
cat(bracket_json)

This will output a JSON structure where every non-leaf node has exactly two children—perfect for d3.hierarchy.

2. Build the Bracket Visualization with D3.js

Now let's use this JSON to create the binary bracket tree. We'll use d3.tree() and adjust the layout to look like a typical basketball bracket:

<!DOCTYPE html>
<html>
<head>
  <script src="https://d3js.org/d3.v7.min.js"></script>
  <style>
    .node circle {
      fill: #fff;
      stroke: steelblue;
      stroke-width: 3px;
    }
    .node text {
      font: 12px sans-serif;
    }
    .link {
      fill: none;
      stroke: #ccc;
      stroke-width: 2px;
    }
  </style>
</head>
<body>
  <svg width="800" height="600"></svg>

  <script>
    // Load the JSON we generated from R
    d3.json("bracket.json").then(function(data) {
      // Create the hierarchy
      const root = d3.hierarchy(data);
      
      // Set up the tree layout - adjust size to fit your bracket
      const treeLayout = d3.tree()
        .size([600, 500]) // [height, width] swapped for horizontal bracket
        .separation(function(a, b) { return (a.parent == b.parent ? 1 : 2) / a.depth; });
      
      // Compute node positions
      treeLayout(root);
      
      const svg = d3.select("svg");
      const g = svg.append("g").attr("transform", "translate(50, 20)");
      
      // Draw links between nodes
      const link = g.selectAll(".link")
        .data(root.links())
        .enter().append("path")
        .attr("class", "link")
        .attr("d", d3.linkHorizontal()
          .x(function(d) { return d.y; })
          .y(function(d) { return d.x; }));
      
      // Draw nodes
      const node = g.selectAll(".node")
        .data(root.descendants())
        .enter().append("g")
        .attr("class", function(d) { return "node" + (d.children ? " node--internal" : " node--leaf"); })
        .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });
      
      node.append("circle")
        .attr("r", 6);
      
      // Add team/round labels
      node.append("text")
        .attr("dy", ".35em")
        .attr("x", function(d) { return d.children ? -12 : 12; })
        .style("text-anchor", function(d) { return d.children ? "end" : "start"; })
        .text(function(d) { return d.data.name; });
    });
  </script>
</body>
</html>

Quick Tips:

  • Layout Adjustments: Tweak the size() parameter in d3.tree() to fit your bracket's number of rounds and overall dimensions.
  • Custom Styling: Modify the CSS to match your brand or desired look—change colors, font sizes, or node shapes easily.
  • Data Checks: Double-check your R data to ensure every non-leaf node has exactly two children; the recursive function includes a basic check, but you can expand it to handle edge cases in your dataset.

内容的提问来源于stack exchange,提问作者Canovice

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:13:00