Skip to content
On this page

Dodge transform

Given one position dimension (either x or y), the dodge transform computes the other position dimension such that dots are packed densely without overlapping. The dodgeX transform computes x (horizontal position) given y (vertical position), while the dodgeY transform computes y given x.

The dodge transform is commonly used to produce beeswarm 🐝 plots, a way of showing a one-dimensional distribution that preserves the visual identity of individual data points. For example, the dots below represent the weights of cars; the rough shape of the pile gives a sense of the overall distribution (peaking around 2,100 pounds), and you can hover an individual dot to see which car it represents.

2,0002,5003,0003,5004,0004,5005,000weight (lb) →AMC Ambassador BroughamAMC Ambassador DPLAMC Ambassador SSTAMC Concord DL 6AMC Concord DLAMC Concord DLAMC ConcordAMC ConcordAMC GremlinAMC GremlinAMC GremlinAMC GremlinAMC Hornet Sportabout (Wagon)AMC HornetAMC HornetAMC HornetAMC HornetAMC Matador (Wagon)AMC Matador (Wagon)AMC MatadorAMC MatadorAMC MatadorAMC MatadorAMC MatadorAMC Pacer D/LAMC PacerAMC Rebel SST (Wagon)AMC Rebel SSTAMC Spirit DLAudi 100 LSAudi 100 LSAudi 100 LSAudi 4000Audi 5000Audi 5000S (Diesel)Audi FoxBMW 2002BMW 320iBuick Century 350Buick Century LimitedBuick Century Luxus (Wagon)Buick Century SpecialBuick CenturyBuick CenturyBuick Electra 225 CustomBuick Estate Wagon (Wagon)Buick Estate Wagon (Wagon)Buick Lesabre CustomBuick Opel Isuzu DeluxeBuick Regal Sport Coupe (Turbo)Buick SkyhawkBuick Skylark 320Buick Skylark LimitedBuick SkylarkBuick SkylarkCadillac EldoradoCadillac SevilleChevroelt Chevelle MalibuChevrolet Bel AirChevrolet CamaroChevrolet Caprice ClassicChevrolet Caprice ClassicChevrolet Caprice ClassicChevrolet Cavalier 2-DoorChevrolet Cavalier WagonChevrolet CavalierChevrolet Chevelle Concours (Wagon)Chevrolet Chevelle Concours (Wagon)Chevrolet Chevelle Malibu ClassicChevrolet Chevelle Malibu ClassicChevrolet Chevelle MalibuChevrolet Chevelle MalibuChevrolet ChevetteChevrolet ChevetteChevrolet ChevetteChevrolet ChevetteChevrolet CitationChevrolet CitationChevrolet CitationChevrolet ConcoursChevrolet ImpalaChevrolet ImpalaChevrolet ImpalaChevrolet ImpalaChevrolet Malibu Classic (Wagon)Chevrolet MalibuChevrolet MalibuChevrolet Monte Carlo LandauChevrolet Monte Carlo LandauChevrolet Monte Carlo SChevrolet Monte CarloChevrolet Monza 2+2Chevrolet Nova CustomChevrolet NovaChevrolet NovaChevrolet NovaChevrolet Vega (Wagon)Chevrolet Vega 2300Chevrolet VegaChevrolet VegaChevrolet VegaChevrolet WoodyChevy C10Chevy C20Chevy S-10Chrysler CordobaChrysler Lebaron MedallionChrysler Lebaron SalonChrysler Lebaron Town & Country (Wagon)Chrysler New Yorker BroughamChrysler Newport RoyalCitroen DS-21 PallasDatsun 1200Datsun 200SXDatsun 200SXDatsun 210Datsun 210Datsun 210Datsun 280ZXDatsun 310 GXDatsun 310Datsun 510 (Wagon)Datsun 510 HatchbackDatsun 510Datsun 610Datsun 710Datsun 710Datsun 810 MaximaDatsun 810Datsun B-210Datsun B210 GXDatsun B210Datsun F-10 HatchbackDatsun PL510Datsun PL510Dodge Aries SEDodge Aries Wagon (Wagon)Dodge Aspen 6Dodge Aspen SEDodge AspenDodge AspenDodge Challenger SEDodge Charger 2.2Dodge Colt (Wagon)Dodge Colt HardtopDodge Colt Hatchback CustomDodge Colt M/MDodge ColtDodge ColtDodge ColtDodge Coronet BroughamDodge Coronet Custom (Wagon)Dodge Coronet CustomDodge D100Dodge D200Dodge Dart CustomDodge DiplomatDodge Magnum XEDodge Monaco (Wagon)Dodge Monaco BroughamDodge OmniDodge RampageDodge St. RegisFiat 124 Sport CoupeFiat 124 TCFiat 124BFiat 128Fiat 128Fiat 131Fiat Strada CustomFiat X1.9Ford Capri IIFord Country Squire (Wagon)Ford Country Squire (Wagon)Ford CountryFord Escort 2HFord Escort 4WFord F108Ford F250Ford Fairmont (Auto)Ford Fairmont (Man)Ford Fairmont 4Ford Fairmont FuturaFord FairmontFord FiestaFord FuturaFord Galaxie 500Ford Galaxie 500Ford Galaxie 500Ford Gran Torino (Wagon)Ford Gran Torino (Wagon)Ford Gran TorinoFord Gran TorinoFord Gran TorinoFord Granada GhiaFord Granada GLFord Granada LFord GranadaFord LTD LandauFord LTDFord LTDFord MaverickFord MaverickFord MaverickFord MaverickFord MaverickFord Mustang Boss 302Ford Mustang CobraFord Mustang GLFord Mustang II 2+2Ford Mustang IIFord MustangFord Pinto (Wagon)Ford Pinto RunaboutFord PintoFord PintoFord PintoFord PintoFord PintoFord PintoFord RangerFord ThunderbirdFord Torino (Wagon)Ford Torino 500Ford TorinoHi 1200DHonda Accord CVCCHonda Accord LXHonda AccordHonda AccordHonda Civic (Auto)Honda Civic 1300Honda Civic 1500 GLHonda Civic CVCCHonda Civic CVCCHonda CivicHonda CivicHonda CivicHonda PreludeMaxda GLC DeluxeMaxda RX-3Mazda 626Mazda 626Mazda GLC 4Mazda GLC Custom LMazda GLC CustomMazda GLC DeluxeMazda GLCMazda RX-2 CoupeMazda RX-4Mazda RX-7 GsMercedes-Benz 240DMercedes-Benz 280SMercedes-Benz 300DMercury Capri 2000Mercury Capri V6Mercury Cougar BroughamMercury Grand MarquisMercury Lynx LMercury Marquis BroughamMercury MarquisMercury Monarch GhiaMercury MonarchMercury Zephyr 6Mercury ZephyrNissan Stanza XEOldsmobile Cutlass Ciera (Diesel)Oldsmobile Cutlass LSOldsmobile Cutlass Salon BroughamOldsmobile Cutlass Salon BroughamOldsmobile Cutlass SupremeOldsmobile Delta 88 RoyaleOldsmobile Omega BroughamOldsmobile OmegaOldsmobile Starfire SXOldsmobile Vista CruiserOpel 1900Opel 1900Opel MantaOpel MantaPeugeot 304Peugeot 504 (Wagon)Peugeot 504Peugeot 504Peugeot 504Peugeot 504Peugeot 505S Turbo DieselPeugeot 604SLPlymouth Arrow GSPlymouth Barracuda 340Plymouth ChampPlymouth CricketPlymouth Custom SuburbPlymouth DusterPlymouth DusterPlymouth DusterPlymouth Fury Gran SedanPlymouth Fury IIIPlymouth Fury IIIPlymouth Fury IIIPlymouth FuryPlymouth Grand FuryPlymouth Horizon 4Plymouth Horizon MiserPlymouth Horizon TC3Plymouth HorizonPlymouth ReliantPlymouth ReliantPlymouth SapporoPlymouth Satellite (Wagon)Plymouth Satellite Custom (Wagon)Plymouth Satellite CustomPlymouth Satellite SebringPlymouth SatellitePlymouth Valiant CustomPlymouth ValiantPlymouth ValiantPlymouth Volare CustomPlymouth Volare Premier V8Plymouth VolarePontiac AstroPontiac Catalina BroughamPontiac CatalinaPontiac CatalinaPontiac CatalinaPontiac FirebirdPontiac Grand Prix LjPontiac Grand PrixPontiac J2000 Se HatchbackPontiac Lemans V6Pontiac Phoenix LJPontiac PhoenixPontiac PhoenixPontiac Safari (Wagon)Pontiac Sunbird CoupePontiac Ventura SjRenault 12 (Wagon)Renault 12TLRenault 18IRenault 5 GtlRenault Lecar DeluxeSaab 900SSaab 99ESaab 99GLESaab 99LESaab 99LESubaru DLSubaru DLSubaruSubaruToyota CarinaToyota Celica GT LiftbackToyota Celica GTToyota Corolla 1200Toyota Corolla 1200Toyota Corolla 1600 (Wagon)Toyota Corolla LiftbackToyota Corolla TercelToyota CorollaToyota CorollaToyota CorollaToyota CorollaToyota CorollaToyota Corona HardtopToyota Corona LiftbackToyota Corona Mark IIToyota CoronaToyota CoronaToyota CoronaToyota CoronaToyota CressidaToyota Mark IIToyota Mark IIToyota StarletToyota TercelToyouta Corona Mark II (Wagon)Triumph TR7 CoupeVokswagen RabbitVolkswagen 1131 Deluxe SedanVolkswagen 411 (Wagon)Volkswagen Dasher (Diesel)Volkswagen DasherVolkswagen DasherVolkswagen DasherVolkswagen JettaVolkswagen Model 111Volkswagen PickupVolkswagen Rabbit C (Diesel)Volkswagen Rabbit Custom DieselVolkswagen Rabbit CustomVolkswagen Rabbit CustomVolkswagen Rabbit LVolkswagen RabbitVolkswagen RabbitVolkswagen RabbitVolkswagen RabbitVolkswagen SciroccoVolkswagen Super Beetle 117Volkswagen Super BeetleVolkswagen Type 3Volvo 144EAVolvo 145E (Wagon)Volvo 244DLVolvo 245Volvo 264GLVolvo DieselFork
js
Plot.plot({
  height: 160,
  marks: [
    Plot.dotX(cars, Plot.dodgeY({x: "weight (lb)", title: "name", fill: "currentColor"}))
  ]
})

Compare this to a conventional histogram using a rect mark.

020406080100↑ Frequency1,5002,0002,5003,0003,5004,0004,5005,0005,500weight (lb) →Fork
js
Plot.plot({
  height: 180,
  marks: [
    Plot.rectY(cars, Plot.binX({y: "count"}, {x: "weight (lb)"})),
    Plot.ruleY([0])
  ]
})

The dodge transform works with Plot’s faceting system, allowing independent beeswarm plots on discrete partitions of the data. Below, penguins are grouped by species and colored by sex, while vertical↕︎ position (y) encodes body mass.

Fork
js
Plot.plot({
  y: {grid: true},
  color: {legend: true},
  marks: [
    Plot.dot(penguins, Plot.dodgeX("middle", {fx: "species", y: "body_mass_g", fill: "sex"}))
  ]
})

Beeswarm plots avoid the occlusion problem of dense scatterplots and barcode plots.

2,0002,5003,0003,5004,0004,5005,000weight (lb) →Fork
js
Plot.dotX(cars, {x: "weight (lb)"}).plot()
2,0002,5003,0003,5004,0004,5005,000weight (lb) →Fork
js
Plot.ruleX(cars, {x: "weight (lb)"}).plot()

The anchor option specifies the layout baseline: the optimal output position. For the dodgeX transform, the supported anchors are: left (default), middle, right. For the dodgeY transform, the supported anchors are: bottom (default), middle, top. When the middle anchor is used, the dots are placed symmetrically around the baseline.

2,0002,5003,0003,5004,0004,5005,000weight (lb) →Fork
js
Plot.plot({
  height: 180,
  marks: [
    Plot.dot(cars, Plot.dodgeY(anchor, {x: "weight (lb)", fill: "currentColor"}))
  ]
})

When using dodgeY, you must typically specify the plot’s height to create suitable space for the layout. The dodge transform is not currently able to set the height automatically. For dodgeX, the default width of 640 is often sufficient, though you may need to adjust it as well depending on your data.

The dodge transform differs from the stack transform in that the dots do not need the exact same input position to avoid overlap; the dodge transform respects the radius r of each dot. Try adjusting the radius below to see the effect.

2,0002,5003,0003,5004,0004,5005,000weight (lb) →Fork
js
Plot.plot({
  height: 180,
  marks: [
    Plot.dot(cars, Plot.dodgeY({x: "weight (lb)", r, fill: "currentColor"}))
  ]
})

The dodge transform also supports a padding option (default 1), which specifies the minimum separating distance between dots. Increase it for more breathing room.

2,0002,5003,0003,5004,0004,5005,000weight (lb) →Fork
js
Plot.plot({
  height: 180,
  marks: [
    Plot.dot(cars, Plot.dodgeY({x: "weight (lb)", padding, fill: "currentColor"}))
  ]
})

If r is a channel, the dodge transform will position circles of varying radius. The chart below shows twenty years of IPO offerings leading up to Facebook’s $104B offering in 2012; each circle is sized proportionally to the associated company’s valuation at IPO. (This data comes from “The Facebook Offering: How It Compares” by Jeremy Ashkenas, Matthew Bloch, Shan Carter, and Amanda Cox.) Facebook’s valuation was nearly four times that of Google, the previous record. The 2000 dot-com bubble is also visible.

Fork
js
Plot.plot({
  insetRight: 10,
  height: 790,
  marks: [
    Plot.dot(
      ipos,
      Plot.dodgeY({
        x: "date",
        r: "rMVOP",
        title: (d) => `${d.NAME}\n${(d.rMVOP / 1e3).toFixed(1)}B`,
        fill: "currentColor"
      })
    ),
    Plot.text(
      ipos,
      Plot.dodgeY({
        filter: (d) => d.rMVOP > 5e3,
        x: "date",
        r: "rMVOP",
        text: (d) => (d.rMVOP / 1e3).toFixed(),
        fill: "white",
        pointerEvents: "none"
      })
    )
  ]
})

The dodge transform can be use with any mark that supports x and y position. Below, we use the text mark instead to show company valuations (in billions).

Fork
js
Plot.plot({
  insetRight: 10,
  height: 790,
  marks: [
    Plot.text(
      ipos,
      Plot.dodgeY({
        x: "date",
        r: "rMVOP",
        text: (d) => (d.rMVOP / 1e3).toFixed(1),
        title: "NAME",
        fontSize: (d) => Math.min(22, Math.cbrt(d.rMVOP / 1e3) * 6)
      })
    )
  ]
})

The dodge transform places dots sequentially, each time finding the closest position to the baseline that avoids intersection with previously-placed dots. Because this is a greedy algorithm, the resulting layout depends on the input order. When r is a channel, dots are sorted by descending radius by default such that the largest dots are placed closest to the baseline. Otherwise, dots are placed in input order by default.

To adjust the dodge layout, use the sort transform. For example, if the sort option uses the same column as x, the dots are arranged in piles leaning right.

2,0002,5003,0003,5004,0004,5005,000weight (lb) →Datsun 1200Toyota CoronaToyota StarletHonda Civic 1300Toyota Corolla 1200Honda Civic CVCCHonda CivicFord FiestaHonda Civic CVCCRenault 5 GtlVolkswagen RabbitVolkswagen Model 111Renault Lecar DeluxeVolkswagen 1131 Deluxe SedanToyota Corolla 1200Vokswagen RabbitHonda Civic 1500 GLFiat 128Plymouth ChampDodge Colt Hatchback CustomVolkswagen Rabbit CustomVolkswagen RabbitVolkswagen RabbitVolkswagen Rabbit CustomDatsun F-10 HatchbackDatsun B210Volkswagen Super BeetlePlymouth CricketVolkswagen DasherHonda Civic (Auto)Honda CivicToyota Corolla TercelMazda GLC CustomDatsun 210Maxda GLC DeluxeVolkswagen Super Beetle 117Volkswagen Rabbit LMazda GLC 4Mazda GLC DeluxeSubaru DLVolkswagen Rabbit Custom DieselDatsun B-210Volkswagen SciroccoDatsun 310 GXFiat X1.9Datsun 710Datsun 310Datsun 210Mazda GLC Custom LChevrolet ChevetteFord Escort 4WHonda Accord CVCCFord PintoToyota TercelChevrolet ChevetteFiat 124BSubaruDatsun B210 GXPeugeot 304Dodge Colt M/MVolkswagen Rabbit C (Diesel)Toyota Corolla 1600 (Wagon)Fiat 128Datsun 210Mazda GLCChevrolet ChevetteOpel 1900Maxda RX-3Dodge ColtMercury Lynx LPlymouth Horizon MiserDodge Colt HardtopDatsun PL510Datsun PL510Fiat Strada CustomVolkswagen PickupHonda Accord LXVolkswagen RabbitSubaru DLPlymouth Horizon TC3Buick Opel Isuzu DeluxeChevrolet ChevetteToyota CorollaOpel MantaNissan Stanza XEChevrolet WoodyDodge Colt (Wagon)Toyota CorollaAudi 4000Renault 12 (Wagon)Volkswagen DasherVolkswagen JettaPlymouth HorizonRenault 12TLHonda AccordHonda PreludePlymouth Horizon 4Audi FoxMercury Capri 2000Opel 1900Volkswagen DasherFord Pinto RunaboutToyota CoronaDodge OmniBMW 2002Toyota CorollaFiat 124 TCVolkswagen Type 3Dodge ColtChevrolet Vega 2300Fiat 124 Sport CoupeToyota Corolla LiftbackToyota CorollaToyota Corona HardtopToyota CarinaDatsun 510 (Wagon)Honda AccordDodge RampageDatsun 510Opel MantaPlymouth Arrow GSFord PintoRenault 18IMazda RX-2 CoupeVolkswagen Dasher (Diesel)Toyota CorollaDodge Charger 2.2Toyota Corona Mark IISaab 99EDatsun 610Ford Escort 2HPlymouth ReliantSubaruChevrolet Cavalier 2-DoorFord Pinto (Wagon)Chevrolet VegaDatsun 200SXChevrolet Vega (Wagon)Chevrolet VegaMazda RX-7 GsAudi 100 LSDatsun 510 HatchbackFord PintoFiat 131Mercury Capri V6Honda CivicPlymouth ReliantTriumph TR7 CoupeToyouta Corona Mark II (Wagon)Volkswagen 411 (Wagon)Toyota Celica GT LiftbackDodge Aries SEChevrolet VegaMazda 626Datsun 710Pontiac PhoenixToyota CoronaFord PintoFord Capri IIPontiac J2000 Se HatchbackAudi 100 LSChrysler Lebaron MedallionFord MaverickPontiac AstroChevrolet CitationBMW 320iChevrolet CavalierDatsun 200SXDodge Aries Wagon (Wagon)Ford RangerAMC GremlinBuick SkylarkMazda 626Ford PintoChevrolet Cavalier WagonAMC GremlinSaab 99LEToyota Celica GTAMC Spirit DLBuick Skylark LimitedSaab 99LEPeugeot 504Chevrolet CitationAudi 100 LSOldsmobile Omega BroughamToyota CoronaToyota Corona LiftbackChevy S-10Ford Fairmont (Man)Mazda RX-4Chevrolet CitationPontiac PhoenixPontiac Sunbird CoupePlymouth SapporoFord Mustang II 2+2AMC HornetAMC GremlinFord Mustang GLSaab 99GLEDodge ColtSaab 900SToyota Mark IIDatsun 810Audi 5000Plymouth DusterFord Granada LOldsmobile Starfire SXFord Fairmont FuturaVolvo 144EAFord FairmontFord MaverickFord Fairmont 4Toyota CressidaAMC HornetPlymouth DusterFord Mustang CobraDatsun 280ZXAMC GremlinDatsun 810 MaximaToyota Mark IIVolvo 145E (Wagon)AMC HornetBuick Century LimitedVolvo 244DLAudi 5000S (Diesel)Chevrolet CamaroPeugeot 504AMC Hornet Sportabout (Wagon)Ford Fairmont (Auto)Peugeot 504 (Wagon)Ford PintoMercury Zephyr 6AMC ConcordFord MaverickOldsmobile Cutlass Ciera (Diesel)Ford MaverickAMC Concord DLBuick SkyhawkFord Granada GLMercury ZephyrAMC HornetBuick Estate Wagon (Wagon)Citroen DS-21 PallasPlymouth DusterPlymouth ValiantFord MustangVolvo 264GLVolvo 245Chevrolet MalibuFord MaverickVolvo DieselFord Mustang IIPeugeot 504AMC Pacer D/LFord FuturaAMC ConcordAMC PacerChevrolet Monza 2+2Peugeot 505S Turbo DieselPlymouth ValiantPontiac Lemans V6Mercedes-Benz 240DPlymouth Valiant CustomAMC Concord DL 6Peugeot 504Chevrolet Nova CustomPontiac FirebirdAMC MatadorFord Torino 500Chevrolet Chevelle MalibuChevrolet NovaChevrolet NovaFord Mustang Boss 302Dodge Aspen 6Oldsmobile Cutlass Salon BroughamBuick Century SpecialDodge AspenDodge Dart CustomAMC Concord DLPeugeot 604SLBuick CenturyOldsmobile Cutlass Salon BroughamBuick SkylarkChevrolet Monte Carlo LandauPlymouth VolareMercury MonarchAMC Rebel SSTPlymouth SatellitePlymouth Satellite CustomBuick Regal Sport Coupe (Turbo)Ford TorinoChevrolet NovaChrysler Lebaron SalonChevrolet Chevelle MalibuChevrolet ConcoursFord GranadaMercedes-Benz 300DPontiac Phoenix LJDodge Challenger SEMercury Monarch GhiaFord Granada GhiaChevrolet Malibu Classic (Wagon)Plymouth Barracuda 340Plymouth Satellite SebringDodge AspenPlymouth Volare CustomAMC MatadorPontiac Ventura SjDodge Aspen SEOldsmobile OmegaAMC Ambassador SSTAMC MatadorBuick Skylark 320Ford LTD LandauOldsmobile Cutlass LSAMC MatadorDodge DiplomatDodge D100Chevrolet Monte CarloDodge Coronet CustomChevrolet Chevelle Malibu ClassicPlymouth FuryMercedes-Benz 280SAMC Ambassador BroughamDodge St. RegisChevrolet Caprice ClassicAMC Ambassador DPLAMC Rebel SST (Wagon)Ford F108Chevrolet Caprice ClassicAMC Matador (Wagon)Chevroelt Chevelle MalibuCadillac EldoradoBuick CenturyChrysler Lebaron Town & Country (Wagon)Plymouth Volare Premier V8Mercury Grand MarquisAMC MatadorChevrolet MalibuFord Torino (Wagon)Ford Gran TorinoFord Country Squire (Wagon)Chevy C10Oldsmobile Cutlass SupremePlymouth Satellite Custom (Wagon)Dodge Magnum XEChevrolet Monte Carlo SPlymouth Fury IIIChevrolet Chevelle Concours (Wagon)Buick Century 350Ford Galaxie 500Plymouth Fury IIIDodge Monaco BroughamFord Gran TorinoChevrolet Chevelle Concours (Wagon)Ford Galaxie 500Chevrolet Monte Carlo LandauPlymouth Satellite (Wagon)Dodge Coronet BroughamChevrolet ImpalaChevrolet Chevelle Malibu ClassicFord Gran TorinoPontiac Grand Prix LjPlymouth Fury Gran SedanAMC Matador (Wagon)Chevrolet ImpalaPontiac Grand PrixFord Gran Torino (Wagon)Mercury Cougar BroughamPlymouth Fury IIIChrysler CordobaFord ThunderbirdFord Galaxie 500Chevrolet ImpalaBuick Estate Wagon (Wagon)Ford LTDChevy C20Cadillac SevilleDodge D200Pontiac CatalinaChrysler Newport RoyalPontiac CatalinaChevrolet Bel AirOldsmobile Delta 88 RoyaleDodge Coronet Custom (Wagon)Chevrolet Caprice ClassicPontiac Catalina BroughamPlymouth Grand FuryOldsmobile Vista CruiserBuick Lesabre CustomFord F250Mercury MarquisFord Gran Torino (Wagon)Plymouth Custom SuburbFord LTDPontiac CatalinaBuick Century Luxus (Wagon)Hi 1200DChrysler New Yorker BroughamFord Country Squire (Wagon)Ford CountryBuick Electra 225 CustomMercury Marquis BroughamDodge Monaco (Wagon)Chevrolet ImpalaPontiac Safari (Wagon)Fork
js
Plot.plot({
  height: 180,
  marks: [
    Plot.dotX(cars, Plot.dodgeY({x: "weight (lb)", title: "name", fill: "currentColor", sort: "weight (lb)"}))
  ]
})

Reversing the sort order produces piles leaning left.

2,0002,5003,0003,5004,0004,5005,000weight (lb) →Pontiac Safari (Wagon)Chevrolet ImpalaDodge Monaco (Wagon)Mercury Marquis BroughamBuick Electra 225 CustomFord CountryFord Country Squire (Wagon)Chrysler New Yorker BroughamHi 1200DBuick Century Luxus (Wagon)Pontiac CatalinaFord LTDPlymouth Custom SuburbFord Gran Torino (Wagon)Mercury MarquisFord F250Buick Lesabre CustomOldsmobile Vista CruiserPlymouth Grand FuryPontiac Catalina BroughamChevrolet Caprice ClassicDodge Coronet Custom (Wagon)Oldsmobile Delta 88 RoyaleChevrolet Bel AirPontiac CatalinaChrysler Newport RoyalPontiac CatalinaDodge D200Cadillac SevilleChevy C20Ford LTDBuick Estate Wagon (Wagon)Chevrolet ImpalaFord Galaxie 500Ford ThunderbirdChrysler CordobaPlymouth Fury IIIMercury Cougar BroughamFord Gran Torino (Wagon)Pontiac Grand PrixChevrolet ImpalaAMC Matador (Wagon)Plymouth Fury Gran SedanPontiac Grand Prix LjFord Gran TorinoChevrolet Chevelle Malibu ClassicChevrolet ImpalaDodge Coronet BroughamPlymouth Satellite (Wagon)Chevrolet Monte Carlo LandauFord Galaxie 500Chevrolet Chevelle Concours (Wagon)Ford Gran TorinoDodge Monaco BroughamPlymouth Fury IIIFord Galaxie 500Buick Century 350Chevrolet Chevelle Concours (Wagon)Plymouth Fury IIIChevrolet Monte Carlo SDodge Magnum XEPlymouth Satellite Custom (Wagon)Oldsmobile Cutlass SupremeChevy C10Ford Country Squire (Wagon)Ford Gran TorinoFord Torino (Wagon)Chevrolet MalibuAMC MatadorMercury Grand MarquisPlymouth Volare Premier V8Chrysler Lebaron Town & Country (Wagon)Buick CenturyCadillac EldoradoChevroelt Chevelle MalibuAMC Matador (Wagon)Chevrolet Caprice ClassicFord F108AMC Rebel SST (Wagon)AMC Ambassador DPLChevrolet Caprice ClassicDodge St. RegisAMC Ambassador BroughamMercedes-Benz 280SPlymouth FuryChevrolet Chevelle Malibu ClassicDodge Coronet CustomChevrolet Monte CarloDodge D100Dodge DiplomatAMC MatadorOldsmobile Cutlass LSFord LTD LandauBuick Skylark 320AMC MatadorAMC Ambassador SSTOldsmobile OmegaDodge Aspen SEPontiac Ventura SjAMC MatadorPlymouth Volare CustomDodge AspenPlymouth Satellite SebringPlymouth Barracuda 340Chevrolet Malibu Classic (Wagon)Ford Granada GhiaMercury Monarch GhiaDodge Challenger SEPontiac Phoenix LJMercedes-Benz 300DFord GranadaChevrolet ConcoursChevrolet Chevelle MalibuChrysler Lebaron SalonChevrolet NovaFord TorinoBuick Regal Sport Coupe (Turbo)Plymouth Satellite CustomPlymouth SatelliteAMC Rebel SSTMercury MonarchPlymouth VolareChevrolet Monte Carlo LandauBuick SkylarkOldsmobile Cutlass Salon BroughamBuick CenturyPeugeot 604SLAMC Concord DLDodge Dart CustomDodge AspenBuick Century SpecialOldsmobile Cutlass Salon BroughamDodge Aspen 6Ford Mustang Boss 302Chevrolet NovaChevrolet NovaChevrolet Chevelle MalibuFord Torino 500AMC MatadorPontiac FirebirdChevrolet Nova CustomPeugeot 504AMC Concord DL 6Plymouth Valiant CustomMercedes-Benz 240DPontiac Lemans V6Plymouth ValiantPeugeot 505S Turbo DieselChevrolet Monza 2+2AMC PacerAMC ConcordFord FuturaAMC Pacer D/LPeugeot 504Ford Mustang IIVolvo DieselFord MaverickChevrolet MalibuVolvo 245Volvo 264GLFord MustangPlymouth ValiantPlymouth DusterCitroen DS-21 PallasBuick Estate Wagon (Wagon)AMC HornetMercury ZephyrFord Granada GLBuick SkyhawkAMC Concord DLFord MaverickOldsmobile Cutlass Ciera (Diesel)Ford MaverickAMC ConcordMercury Zephyr 6Ford PintoPeugeot 504 (Wagon)Ford Fairmont (Auto)AMC Hornet Sportabout (Wagon)Peugeot 504Chevrolet CamaroAudi 5000S (Diesel)Volvo 244DLBuick Century LimitedAMC HornetVolvo 145E (Wagon)Toyota Mark IIDatsun 810 MaximaAMC GremlinDatsun 280ZXFord Mustang CobraPlymouth DusterAMC HornetToyota CressidaFord Fairmont 4Ford MaverickFord FairmontVolvo 144EAFord Fairmont FuturaOldsmobile Starfire SXFord Granada LPlymouth DusterAudi 5000Datsun 810Toyota Mark IISaab 900SDodge ColtSaab 99GLEFord Mustang GLAMC GremlinAMC HornetFord Mustang II 2+2Plymouth SapporoPontiac Sunbird CoupePontiac PhoenixChevrolet CitationMazda RX-4Ford Fairmont (Man)Chevy S-10Toyota Corona LiftbackToyota CoronaOldsmobile Omega BroughamAudi 100 LSChevrolet CitationPeugeot 504Saab 99LEBuick Skylark LimitedAMC Spirit DLToyota Celica GTSaab 99LEAMC GremlinChevrolet Cavalier WagonFord PintoMazda 626Buick SkylarkAMC GremlinFord RangerDodge Aries Wagon (Wagon)Datsun 200SXChevrolet CavalierBMW 320iChevrolet CitationPontiac AstroFord MaverickChrysler Lebaron MedallionAudi 100 LSPontiac J2000 Se HatchbackFord Capri IIFord PintoToyota CoronaPontiac PhoenixDatsun 710Mazda 626Chevrolet VegaDodge Aries SEToyota Celica GT LiftbackVolkswagen 411 (Wagon)Toyouta Corona Mark II (Wagon)Triumph TR7 CoupePlymouth ReliantHonda CivicMercury Capri V6Fiat 131Ford PintoDatsun 510 HatchbackAudi 100 LSMazda RX-7 GsChevrolet VegaChevrolet Vega (Wagon)Datsun 200SXChevrolet VegaFord Pinto (Wagon)Chevrolet Cavalier 2-DoorSubaruPlymouth ReliantFord Escort 2HDatsun 610Saab 99EToyota Corona Mark IIDodge Charger 2.2Toyota CorollaVolkswagen Dasher (Diesel)Mazda RX-2 CoupeRenault 18IFord PintoPlymouth Arrow GSOpel MantaDatsun 510Dodge RampageHonda AccordDatsun 510 (Wagon)Toyota CarinaToyota Corona HardtopToyota CorollaToyota Corolla LiftbackFiat 124 Sport CoupeChevrolet Vega 2300Dodge ColtVolkswagen Type 3Fiat 124 TCToyota CorollaBMW 2002Dodge OmniToyota CoronaFord Pinto RunaboutVolkswagen DasherOpel 1900Mercury Capri 2000Audi FoxPlymouth Horizon 4Honda PreludeHonda AccordRenault 12TLPlymouth HorizonVolkswagen JettaVolkswagen DasherRenault 12 (Wagon)Audi 4000Toyota CorollaDodge Colt (Wagon)Chevrolet WoodyNissan Stanza XEOpel MantaToyota CorollaChevrolet ChevetteBuick Opel Isuzu DeluxePlymouth Horizon TC3Subaru DLVolkswagen RabbitHonda Accord LXVolkswagen PickupFiat Strada CustomDatsun PL510Datsun PL510Dodge Colt HardtopPlymouth Horizon MiserMercury Lynx LDodge ColtMaxda RX-3Opel 1900Chevrolet ChevetteMazda GLCDatsun 210Fiat 128Toyota Corolla 1600 (Wagon)Volkswagen Rabbit C (Diesel)Dodge Colt M/MPeugeot 304Datsun B210 GXSubaruFiat 124BChevrolet ChevetteToyota TercelFord PintoHonda Accord CVCCFord Escort 4WChevrolet ChevetteMazda GLC Custom LDatsun 210Datsun 310Datsun 710Fiat X1.9Datsun 310 GXVolkswagen SciroccoDatsun B-210Volkswagen Rabbit Custom DieselSubaru DLMazda GLC DeluxeMazda GLC 4Volkswagen Rabbit LVolkswagen Super Beetle 117Maxda GLC DeluxeDatsun 210Mazda GLC CustomToyota Corolla TercelHonda CivicHonda Civic (Auto)Volkswagen DasherPlymouth CricketVolkswagen Super BeetleDatsun B210Datsun F-10 HatchbackVolkswagen Rabbit CustomVolkswagen RabbitVolkswagen RabbitVolkswagen Rabbit CustomDodge Colt Hatchback CustomPlymouth ChampFiat 128Honda Civic 1500 GLVokswagen RabbitToyota Corolla 1200Volkswagen 1131 Deluxe SedanRenault Lecar DeluxeVolkswagen Model 111Volkswagen RabbitRenault 5 GtlHonda Civic CVCCFord FiestaHonda CivicHonda Civic CVCCToyota Corolla 1200Honda Civic 1300Toyota StarletToyota CoronaDatsun 1200Fork
js
Plot.plot({
  height: 180,
  marks: [
    Plot.dotX(cars, Plot.dodgeY({x: "weight (lb)", title: "name", fill: "currentColor", sort: "weight (lb)", reverse: true}))
  ]
})

TIP

To avoid repeating a channel definition, you can also specify the sort option as {channel: "x"}.

INFO

Unlike a force-directed beeswarm, the dodge transform exactly preserves the input position dimension, resulting in a more accurate visualization. Also, the dodge transform tends to be faster than the iterative constraint relaxation used in the force-directed approach. We use Mikola Lysenko’s interval-tree-1d library for fast intersection testing.

Dodge options

The dodge transforms accept the following options:

  • padding — a number of pixels added to the radius of the mark to estimate its size
  • anchor - the dodge anchor; defaults to left for dodgeX, or bottom for dodgeY

The anchor option may one of middle, right, and left for dodgeX, and one of middle, top, and bottom for dodgeY. With the middle anchor the piles will grow from the center in both directions; with the other anchors, the piles will grow from the specified anchor towards the opposite direction.

dodgeY(dodgeOptions, options)

js
Plot.dodgeY({x: "date"})

Given marks arranged along the x axis, the dodgeY transform piles them vertically by defining a y position channel that avoids overlapping. The x position channel is unchanged.

dodgeX(dodgeOptions, options)

js
Plot.dodgeX({y: "value"})

Equivalent to Plot.dodgeY, but piling horizontally, creating a new x position channel that avoids overlapping. The y position channel is unchanged.

Library released under ISC License.