[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6KJSN6R9BBA26JC7Q4QCT2T":3,"skill-same:01M6KJSN6R9BBA26JC7Q4QCT2T":75},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":27,"publishedAt":48,"linkOnly":49,"markdownContent":50,"markdownBody":51,"frontMatter":52,"refName":53,"commitSha":54,"skillDirectory":55,"forksCount":56,"repositoryHtmlUrl":57,"repositoryHomepageUrl":58,"ownerHtmlUrl":59,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":60,"install":61,"resources":74},"01M6KJSN6R9BBA26JC7Q4QCT2T","d3-force-bubble-chart",null,"Create sector-clustered bubble charts with D3.js force simulation. Use this skill when building bubble charts that need to cluster elements by category (sectors, regions, types), avoid overlap, size bubbles by numeric values, and organize clusters spatially. Common patterns include market analysis dashboards, portfolio visualizations, and categorical bubble charts with dynamic clustering.","cxcscmu\u002FSkillLearnBench","cxcscmu","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F142838272?v=4","01M6KCQDFQWPDSN0MKZY96MSQP","01M6KCQDM7G70TKJ28NTSQC0RZ",93,"MIT","https:\u002F\u002Fgithub.com\u002Fcxcscmu\u002FSkillLearnBench\u002Fblob\u002Fmain\u002Fskills\u002Fb4-skill-creator-claude-haiku-4-5\u002Fstock-data-visualization\u002Fd3-force-bubble-chart\u002FSKILL.md",[17,22],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000013","分析与可视化","SCENARIO","使用场景",{"categoryNo":23,"categoryName":24,"taxonomyType":25,"taxonomyTypeDesc":26},"01JBSEEDCAT000000000000033","数据分析师","PROFESSION","适用职业",[28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47],"d3 force bubble","d3 force bubble chart","d3","chart","elements","values","size","with","types","cluster","create","market analysis","Market","portfolio","use","common","visualizations","simulation","Charts","analysis","2026-11-10 10:12:30",false,"---\nname: d3-force-bubble-chart\ndescription: Create sector-clustered bubble charts with D3.js force simulation. Use this skill when building bubble charts that need to cluster elements by category (sectors, regions, types), avoid overlap, size bubbles by numeric values, and organize clusters spatially. Common patterns include market analysis dashboards, portfolio visualizations, and categorical bubble charts with dynamic clustering.\n---\n\n# D3.js Force Simulation Bubble Chart\n\nThis skill covers how to build interactive, clustered bubble charts using D3 v6 force simulation.\n\n## Key Components\n\n### 1. Force Simulation Setup\n\nCreate a force simulation that organizes bubbles into sector clusters:\n\n```javascript\nconst simulation = d3.forceSimulation(data)\n  .force(\"x\", d3.forceX()\n    .strength(0.05)\n    .x(d => xPositionBySector(d.sector)))\n  .force(\"y\", d3.forceY()\n    .strength(0.05)\n    .y(d => yPositionBySector(d.sector)))\n  .force(\"collide\", d3.forceCollide()\n    .radius(d => d.radius + 2))\n  .force(\"charge\", d3.forceManyBody().strength(-30))\n  .on(\"tick\", updatePositions);\n```\n\n**Why these forces:**\n- **forceX\u002FforceY**: Pull bubbles toward sector-specific positions, creating clusters\n- **forceCollide**: Prevents bubble overlap by pushing circles apart when they collide\n- **forceManyBody**: Adds repulsion to prevent tight clustering (negative strength = repulsion)\n\n### 2. Sector Clustering Strategy\n\nDefine center positions for each sector. Common approaches:\n\n**Grid layout (simple, predictable):**\n```javascript\nfunction getSectorPosition(sector, sectors) {\n  const index = sectors.indexOf(sector);\n  const cols = Math.ceil(Math.sqrt(sectors.length));\n  const x = (index % cols) * (width \u002F cols) + width \u002F (cols * 2);\n  const y = Math.floor(index \u002F cols) * (height \u002F 2) + height \u002F 4;\n  return {x, y};\n}\n```\n\n**Circle layout (more compact):**\n```javascript\nfunction getSectorPosition(sector, sectors) {\n  const index = sectors.indexOf(sector);\n  const angle = (index \u002F sectors.length) * 2 * Math.PI;\n  const radius = 150;\n  return {\n    x: width \u002F 2 + radius * Math.cos(angle),\n    y: height \u002F 2 + radius * Math.sin(angle)\n  };\n}\n```\n\n### 3. Bubble Sizing\n\nSize bubbles proportionally to numeric values (market cap):\n\n```javascript\nconst radiusScale = d3.scaleSqrt()\n  .domain([0, d3.max(data, d => d.marketCap || 0)])\n  .range([3, 40]);\n\ndata.forEach(d => {\n  d.radius = d.marketCap ? radiusScale(d.marketCap) : 20; \u002F\u002F Default for ETFs\n});\n```\n\n**Why `scaleSqrt`:** Area scales linearly with value (perceived area = value)\n\n### 4. Color by Sector\n\n```javascript\nconst colorScale = d3.scaleOrdinal()\n  .domain(sectors)\n  .range(d3.schemeSet2); \u002F\u002F or d3.schemeCategory10, etc.\n```\n\n### 5. Labels Inside Bubbles\n\nEnsure text remains readable inside bubbles:\n\n```javascript\nsvg.selectAll(\"text\")\n  .attr(\"x\", d => d.x)\n  .attr(\"y\", d => d.y)\n  .attr(\"text-anchor\", \"middle\")\n  .attr(\"dy\", \"0.3em\")\n  .attr(\"font-size\", d => Math.max(10, d.radius * 0.4) + \"px\")\n  .attr(\"pointer-events\", \"none\")\n  .text(d => d.ticker);\n```\n\n### 6. Handling Missing Data\n\nFor ETFs (no market cap):\n- Set to default radius: `d.radius = 20`\n- Still cluster by sector\n- Don't exclude from visualization\n- Optionally use different styling (stroke, opacity) to indicate missing data\n\n### 7. Hover Tooltips\n\n```javascript\ncircles.on(\"mouseover\", function(event, d) {\n  if (!d.marketCap) return; \u002F\u002F Skip ETFs\n\n  const tooltip = d3.select(\"body\").append(\"div\")\n    .attr(\"class\", \"tooltip\")\n    .html(`\u003Cstrong>${d.ticker}\u003C\u002Fstrong>\u003Cbr\u002F>${d.name}\u003Cbr\u002F>${d.sector}`);\n\n  tooltip\n    .style(\"left\", (event.pageX + 10) + \"px\")\n    .style(\"top\", (event.pageY - 28) + \"px\");\n})\n.on(\"mouseout\", function() {\n  d3.selectAll(\".tooltip\").remove();\n});\n```\n\n## Performance Tips\n\n- Use `simulation.alpha(0)` after manual positioning to skip initial layout\n- Limit to 100-200 nodes for smooth animations; beyond that, optimize with quadtrees\n- Cache radius calculations instead of computing in loops\n\n## Testing Checklist\n\n- [ ] Bubbles cluster by sector visually\n- [ ] No overlapping bubbles (forceCollide working)\n- [ ] Bubbles sized proportionally to market cap\n- [ ] Text labels fit inside bubbles\n- [ ] ETFs sized uniformly, no tooltips shown\n- [ ] Sector colors distinct and consistent with legend\n","# D3.js Force Simulation Bubble Chart\n\nThis skill covers how to build interactive, clustered bubble charts using D3 v6 force simulation.\n\n## Key Components\n\n### 1. Force Simulation Setup\n\nCreate a force simulation that organizes bubbles into sector clusters:\n\n```javascript\nconst simulation = d3.forceSimulation(data)\n  .force(\"x\", d3.forceX()\n    .strength(0.05)\n    .x(d => xPositionBySector(d.sector)))\n  .force(\"y\", d3.forceY()\n    .strength(0.05)\n    .y(d => yPositionBySector(d.sector)))\n  .force(\"collide\", d3.forceCollide()\n    .radius(d => d.radius + 2))\n  .force(\"charge\", d3.forceManyBody().strength(-30))\n  .on(\"tick\", updatePositions);\n```\n\n**Why these forces:**\n- **forceX\u002FforceY**: Pull bubbles toward sector-specific positions, creating clusters\n- **forceCollide**: Prevents bubble overlap by pushing circles apart when they collide\n- **forceManyBody**: Adds repulsion to prevent tight clustering (negative strength = repulsion)\n\n### 2. Sector Clustering Strategy\n\nDefine center positions for each sector. Common approaches:\n\n**Grid layout (simple, predictable):**\n```javascript\nfunction getSectorPosition(sector, sectors) {\n  const index = sectors.indexOf(sector);\n  const cols = Math.ceil(Math.sqrt(sectors.length));\n  const x = (index % cols) * (width \u002F cols) + width \u002F (cols * 2);\n  const y = Math.floor(index \u002F cols) * (height \u002F 2) + height \u002F 4;\n  return {x, y};\n}\n```\n\n**Circle layout (more compact):**\n```javascript\nfunction getSectorPosition(sector, sectors) {\n  const index = sectors.indexOf(sector);\n  const angle = (index \u002F sectors.length) * 2 * Math.PI;\n  const radius = 150;\n  return {\n    x: width \u002F 2 + radius * Math.cos(angle),\n    y: height \u002F 2 + radius * Math.sin(angle)\n  };\n}\n```\n\n### 3. Bubble Sizing\n\nSize bubbles proportionally to numeric values (market cap):\n\n```javascript\nconst radiusScale = d3.scaleSqrt()\n  .domain([0, d3.max(data, d => d.marketCap || 0)])\n  .range([3, 40]);\n\ndata.forEach(d => {\n  d.radius = d.marketCap ? radiusScale(d.marketCap) : 20; \u002F\u002F Default for ETFs\n});\n```\n\n**Why `scaleSqrt`:** Area scales linearly with value (perceived area = value)\n\n### 4. Color by Sector\n\n```javascript\nconst colorScale = d3.scaleOrdinal()\n  .domain(sectors)\n  .range(d3.schemeSet2); \u002F\u002F or d3.schemeCategory10, etc.\n```\n\n### 5. Labels Inside Bubbles\n\nEnsure text remains readable inside bubbles:\n\n```javascript\nsvg.selectAll(\"text\")\n  .attr(\"x\", d => d.x)\n  .attr(\"y\", d => d.y)\n  .attr(\"text-anchor\", \"middle\")\n  .attr(\"dy\", \"0.3em\")\n  .attr(\"font-size\", d => Math.max(10, d.radius * 0.4) + \"px\")\n  .attr(\"pointer-events\", \"none\")\n  .text(d => d.ticker);\n```\n\n### 6. Handling Missing Data\n\nFor ETFs (no market cap):\n- Set to default radius: `d.radius = 20`\n- Still cluster by sector\n- Don't exclude from visualization\n- Optionally use different styling (stroke, opacity) to indicate missing data\n\n### 7. Hover Tooltips\n\n```javascript\ncircles.on(\"mouseover\", function(event, d) {\n  if (!d.marketCap) return; \u002F\u002F Skip ETFs\n\n  const tooltip = d3.select(\"body\").append(\"div\")\n    .attr(\"class\", \"tooltip\")\n    .html(`\u003Cstrong>${d.ticker}\u003C\u002Fstrong>\u003Cbr\u002F>${d.name}\u003Cbr\u002F>${d.sector}`);\n\n  tooltip\n    .style(\"left\", (event.pageX + 10) + \"px\")\n    .style(\"top\", (event.pageY - 28) + \"px\");\n})\n.on(\"mouseout\", function() {\n  d3.selectAll(\".tooltip\").remove();\n});\n```\n\n## Performance Tips\n\n- Use `simulation.alpha(0)` after manual positioning to skip initial layout\n- Limit to 100-200 nodes for smooth animations; beyond that, optimize with quadtrees\n- Cache radius calculations instead of computing in loops\n\n## Testing Checklist\n\n- [ ] Bubbles cluster by sector visually\n- [ ] No overlapping bubbles (forceCollide working)\n- [ ] Bubbles sized proportionally to market cap\n- [ ] Text labels fit inside bubbles\n- [ ] ETFs sized uniformly, no tooltips shown\n- [ ] Sector colors distinct and consistent with legend\n",{"name":5,"description":7},"main","726e1f79b96b0cb3d729d0e55a1c847e0b5353ae","skills\u002Fb4-skill-creator-claude-haiku-4-5\u002Fstock-data-visualization\u002Fd3-force-bubble-chart",7,"https:\u002F\u002Fgithub.com\u002Fcxcscmu\u002FSkillLearnBench","https:\u002F\u002Fcxcscmu.github.io\u002FSkillLearnBench","https:\u002F\u002Fgithub.com\u002Fcxcscmu","2026-10-02 22:55:36",{"source":8,"skillName":5,"commands":62,"prompt":72,"zipAvailable":73},[63,66,69],{"tool":64,"command":65},"npx","npx skills add cxcscmu\u002FSkillLearnBench --skill d3-force-bubble-chart",{"tool":67,"command":68},"bunx","bunx skills add cxcscmu\u002FSkillLearnBench --skill d3-force-bubble-chart",{"tool":70,"command":71},"pnpm","pnpm dlx skills add cxcscmu\u002FSkillLearnBench --skill d3-force-bubble-chart","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fcxcscmu\u002FSkillLearnBench\u002Fblob\u002Fmain\u002Fskills\u002Fb4-skill-creator-claude-haiku-4-5\u002Fstock-data-visualization\u002Fd3-force-bubble-chart\u002FSKILL.md",true,[],[76,92,117,135,155,167],{"skillNo":77,"name":78,"nameZh":6,"description":79,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":80,"categories":81,"keywords":85,"publishedAt":48},"01M6KM5KH175P5ABP5JMX2SBDQ","object_counter","Count occurrences of an object in the image using computer vision algorithm.","https:\u002F\u002Fgithub.com\u002Fcxcscmu\u002FSkillLearnBench\u002Fblob\u002Fmain\u002Fskills\u002Fhuman_authored\u002Fvideo-object-counting\u002Fobject_counter\u002FSKILL.md",[82],{"categoryNo":83,"categoryName":84,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000016","图像与多媒体",[86,87,88,89,90,91],"object counter","object","vision","computer","Computer Vision","image",{"skillNo":93,"name":94,"nameZh":6,"description":95,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":96,"categories":97,"keywords":101,"publishedAt":48},"01M6KM51TMVXG79MMPCS6Y8G86","travel-planning-workflow","Invoke this skill when performing travel planning. It defines a structured workflow for generating itineraries. Following this workflow is essential to ensure the final plan satisfies user requirements.","https:\u002F\u002Fgithub.com\u002Fcxcscmu\u002FSkillLearnBench\u002Fblob\u002Fmain\u002Fskills\u002Fhuman_authored\u002Ftravel-planning\u002Ftravel-planning-workflow\u002FSKILL.md",[98],{"categoryNo":99,"categoryName":100,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000023","Skill与智能体开发",[102,103,104,105,106,107,108,109,110,111,112,113,114,115,116],"workflow","planning","planning workflow","travel","travel planning","travel planning workflow","structured","performing","plan","for","user","it","requirements","essential","itineraries",{"skillNo":118,"name":119,"nameZh":6,"description":120,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":121,"categories":122,"keywords":123,"publishedAt":48},"01M6KM4DY820XHS9YTSK5QP5HD","bundled-dataset-search-tool","invoke this skill when you need to perform database search for travel planning. This skill provides some useful pre-packaged tools to look up accommodations, attractions, cities, driving distance, flights, and restaurants from the bundled dataset.","https:\u002F\u002Fgithub.com\u002Fcxcscmu\u002FSkillLearnBench\u002Fblob\u002Fmain\u002Fskills\u002Fhuman_authored\u002Ftravel-planning\u002Fbundled-dataset-search-tool\u002FSKILL.md",[],[124,125,126,127,128,129,130,105,131,132,106,133,111,134,103],"search","tool","dataset","bundled dataset search tool","restaurants","Tools","up","look","flights","you","database",{"skillNo":136,"name":137,"nameZh":6,"description":138,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":139,"categories":140,"keywords":141,"publishedAt":48},"01M6KM465BB9PQ0B548HQSVAWZ","glm-output","Output-processing guidance for GLM tasks. Especially useful after glm-basics and glm-calibration when you need verifier-matching metrics from output.nc and a final \u002Froot\u002Fmetrics.json.","https:\u002F\u002Fgithub.com\u002Fcxcscmu\u002FSkillLearnBench\u002Fblob\u002Fmain\u002Fskills\u002Fhuman_authored\u002Ftemperature-simulation\u002Fglm-output\u002FSKILL.md",[],[142,143,144,111,145,146,147,148,149,150,151,152,133,153,154],"glm output","output","glm","tasks","metrics","json","basics","guidance","matching","verifier","processing","root","calibration",{"skillNo":156,"name":157,"nameZh":6,"description":158,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":159,"categories":160,"keywords":162,"publishedAt":48},"01M6KM40KY3QWDW5W97S39R2BC","glm-calibration","Calibration guidance for GLM tasks. Often most effective after glm-basics has clarified the setup; glm-output is the companion skill for exact final metric computation.","https:\u002F\u002Fgithub.com\u002Fcxcscmu\u002FSkillLearnBench\u002Fblob\u002Fmain\u002Fskills\u002Fhuman_authored\u002Ftemperature-simulation\u002Fglm-calibration\u002FSKILL.md",[161],{"categoryNo":99,"categoryName":100,"taxonomyType":20,"taxonomyTypeDesc":21},[163,154,144,143,149,148,145,164,165,111,166],"glm calibration","setup","companion","metric",{"skillNo":168,"name":169,"nameZh":6,"description":170,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":171,"categories":172,"keywords":173,"publishedAt":48},"01M6KM3VHHVSGMGHJQB3PPT6YG","glm-basics","A good starting point for GLM calibration tasks. Use to inspect glm3.nml, confirm how GLM runs, and identify the relevant files before moving on to calibration and output evaluation.","https:\u002F\u002Fgithub.com\u002Fcxcscmu\u002FSkillLearnBench\u002Fblob\u002Fmain\u002Fskills\u002Fhuman_authored\u002Ftemperature-simulation\u002Fglm-basics\u002FSKILL.md",[],[174,144,148,175,163,154,111,143,176,177,178,42,179,180,145],"glm basics","inspect","relevant","files","good","how","Evaluation"]