Skip to content

Add LineCollection plot - #7173

Merged
Illviljan merged 159 commits into
pydata:mainfrom
Illviljan:plot1d_lines
Sep 29, 2026
Merged

Illviljan merged 159 commits into
pydata:mainfrom
Illviljan:plot1d_lines

Conversation

@Illviljan

@Illviljan Illviljan commented Oct 16, 2022 •

Copy link
Copy Markdown
Contributor

This adds a line plotter based on LineCollections, called .lines.

I wanted to replace darray.plot() with using LineCollection instead. But unfortunately due to how many cases are supported (and tested in xarray) darray.plot() will continue using plt.plot.

Examples:

https://www.reddit.com/r/dataisbeautiful/comments/1d4ahr1/oc_north_atlantic_sea_surface_temperature_anomaly/

Got this working with xarray:

Details
# https://www.reddit.com/r/dataisbeautiful/comments/1d4ahr1/oc_north_atlantic_sea_surface_temperature_anomaly/#lightbox
# https://github.com/afinemax/climate_change_bot/blob/main/bot.py


import requests

import numpy as np
import matplotlib.pyplot as plt
import xarray as xr


def download_json(url):
    try:
        response = requests.get(url)
        response.raise_for_status()  # Raise an exception for unsuccessful responses (4xx, 5xx)
        json_data = response.json()
        return json_data
    except requests.exceptions.RequestException as e:
        print(f"Error downloading JSON: {e}")
        return None


url = r"https://climatereanalyzer.org/clim/sst_daily/json/oisst2.1_natlan1_sst_day.json"
sst_daily_data = download_json(url)


data = []
years = []
for i in range(len(sst_daily_data) - 3):
    years.append((sst_daily_data[i]["name"]))
    data.append(sst_daily_data[i]["data"])

# convert data from list into nd arr
data = np.asarray(data, dtype=float)  # first index is year, 2nd index is day

# Datetimes not working for some unrelated reason:
# ds = xr.Dataset(
#     data_vars=dict(temperature=(("year", "day"), data)),
#     coords=dict(
#         year=np.array(dict_names, dtype="datetime64[D]"),
#         day=np.arange(data.shape[-1], dtype="timedelta64[D]"),
#     ),
# )
ds = xr.Dataset(
    data_vars=dict(
        temperature=(
            ("year", "day"),
            data,
            dict(
                long_name="Daily North Atlantic (0-60N) Sea Surface Temperature (SST)",
                units="degC",
            ),
        )
    ),
    coords=dict(
        year=np.array(years, dtype=int),
        day=np.arange(data.shape[-1], dtype=int),
    ),
)

plt.figure()
ds.plot.lines(x="day", y="temperature", hue="year")

image

Calling it lines since scatter is not called path_collection:

  • PathCollection (Very low-level, e.g. no datetime handling) -> plt.scatter (Handles datetime etc.)-> xr.plot.scatter
  • LineCollection (Very low-level, e.g. no datetime handling) -> _line (Handles datetime etc. Pretty much a copy of plt.scatter) -> xr.plot.lines

Seaborns new object-based plotting uses lines as well with similar argument:
https://seaborn.pydata.org/generated/seaborn.objects.Line.html
https://seaborn.pydata.org/generated/seaborn.objects.Lines.html

xref:
#4820
#5622

@Illviljan

Illviljan commented Oct 17, 2022 •

Copy link
Copy Markdown
Contributor Author

Scatter vs. Lines:

image

Details
ds = xr.tutorial.scatter_example_dataset(seed=42)
hue_ = "y"
x_ = "y"
size_="y"
z_ = "z"

fig = plt.figure()
ax = fig.add_subplot(1, 2, 1, projection='3d')
ds.A.sel(w="one").plot.lines(x=x_, z=z_, hue=hue_, linewidth=size_, ax=ax)
ax = fig.add_subplot(1, 2, 2, projection='3d')
ds.A.sel(w="one").plot.scatter(x=x_, z=z_, hue=hue_, markersize=size_, ax=ax)

headtr1ck and others added 2 commits September 29, 2026 11:47
Resolve the conflict with the migration of doc/user-guide/plotting.rst
to myst (pydata#11456) by porting the new Lines section to plotting.md, and
move the whats-new entry to the unreleased section.

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Claude <noreply@anthropic.com>
@headtr1ck

Copy link
Copy Markdown
Collaborator

@Illviljan anything against finally merging this?

@Illviljan

Copy link
Copy Markdown
Contributor Author

No, let's do it.

@headtr1ck
headtr1ck enabled auto-merge (squash) September 29, 2026 20:13
@Illviljan
Illviljan disabled auto-merge September 29, 2026 21:31
@Illviljan
Illviljan merged commit f515b4d into pydata:main Sep 29, 2026
43 of 44 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

plan to merge Final call for comments topic-plotting

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants