Как соединить точки данных линией, где значения отсутствуют

Мне нужно нарисовать несколько изменений биомаркеров по дате на одном графике, но образцы биомаркеров были измерены в разные даты и разное время, например:

data = {
    'PatientID': [244651, 244651, 244651, 244651, 244652, 244653, 244651],
    'LocationType': ['IP', 'IP', 'OP', 'IP', 'IP', 'OP', 'IP'],
    'Date': ['2023-01-01', '2023-01-02', '2023-01-03', '2023-01-04', '2023-01-01', '2023-01-01', '2023-01-05'],
    'Biomarker1': [1.1, 1.2, None, 1.4, 2.1, 3.1, 1.5],
    'Biomarker2': [2.1, None, 2.3, 2.4, 3.1, 4.1, 2.5],
    'Biomarker3': [3.1, 3.2, 3.3, None, 4.1, 5.1, 3.5]
}

нарисовать график:

# Set the date as the index
filtered_df.set_index('Date', inplace=True)

# Plot all biomarkers
plt.figure(figsize=(12, 8))

# Loop through each biomarker column to plot
for column in filtered_df.columns:
    if column not in ['PatientID', 'LocationType']:
        plt.plot(filtered_df.index, filtered_df[column], marker='o', linestyle='-', label=column)

вот мой результат: Изменение биомаркеров со временем

Мне нужно, чтобы все точки одного биомаркера были связаны именно с линией. Я не могу использовать интерполяцию, точки должны быть просто соединены линией.

Как мне это сделать? Пожалуйста помоги!

Я пробовал интерполировать, но создаются новые точки, новые точки мне не нужны.

Вот полный код:

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

# Sample DataFrame (replace this with your actual DataFrame)
data = {
    'PatientID': [244651, 244651, 244651, 244651, 244652, 244653, 244651],
    'LocationType': ['IP', 'IP', 'OP', 'IP', 'IP', 'OP', 'IP'],
    'Date': ['2023-01-01', '2023-01-02', '2023-01-03', '2023-01-04', '2023-01-01', '2023-01-01', '2023-01-05'],
    'Biomarker1': [1.1, 1.2, None, 1.4, 2.1, 3.1, 1.5],
    'Biomarker2': [2.1, None, 2.3, 2.4, 3.1, 4.1, 2.5],
    'Biomarker3': [3.1, 3.2, 3.3, None, 4.1, 5.1, 3.5]
}

# Create DataFrame
df = pd.DataFrame(data)
df['Date'] = pd.to_datetime(df['Date'])

# Filter the data for the specified patient ID and IP location type
filtered_df = df[(df['PatientID'] == 244651) & (df['LocationType'] == 'IP')]

# Set the date as the index
filtered_df.set_index('Date', inplace=True)

# Plot all biomarkers
plt.figure(figsize=(12, 8))

# Loop through each biomarker column to plot each one separately
for column in filtered_df.columns:
    if column not in ['PatientID', 'LocationType']:
        plt.plot(filtered_df.index, filtered_df[column], marker='o', linestyle='-', label=column)

plt.title('Biomarkers by Date for Patient ID 244651 (IP Location Type)')
plt.xlabel('Date')
plt.ylabel('Biomarker Value')
plt.legend()
plt.grid(True)
plt.xticks(rotation=45)
plt.show()

К вашему сведению, предоставленный вами код не создает связанный график.

Ian Thompson 23.05.2024 17:38

@IanThompson добавил полный код, и вы также можете увидеть выходной график по ссылке, мне просто нужно соединить эти зеленые точки и оранжевые точки, но без добавления новых точек. Возможно ли это вообще?

asi 24.05.2024 01:26
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
2
95
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете использовать интерполяцию для завершения строк, а затем добавить неинтерполированные данные сверху, например:

from matplotlib import pyplot as plt
# For color matching.
from matplotlib.colors import TABLEAU_COLORS
import pandas as pd

# Set-up.
data = {
    'PatientID': [244651, 244651, 244651, 244651, 244652, 244653, 244651],
    'LocationType': ['IP', 'IP', 'OP', 'IP', 'IP', 'OP', 'IP'],
    'Date': ['2023-01-01', '2023-01-02', '2023-01-03', '2023-01-04', '2023-01-01', '2023-01-01', '2023-01-05'],
    'Biomarker1': [1.1, 1.2, None, 1.4, 2.1, 3.1, 1.5],
    'Biomarker2': [2.1, None, 2.3, 2.4, 3.1, 4.1, 2.5],
    'Biomarker3': [3.1, 3.2, 3.3, None, 4.1, 5.1, 3.5]
}

df = pd.DataFrame(data)
df = df.set_index("Date")

# To match your filtered data.
filtered_df = df.loc[
    df.PatientID.eq(244651)
    & df.LocationType.eq("IP")
]
# Limit columns to plot.
cols_to_plot = df.loc(axis = "columns")["Biomarker1":].columns
# Interpolate to fill missing values (used to plot lines, not markers).
interpolated_df = filtered_df[cols_to_plot].interpolate()

# Plot everything.
fig, ax = plt.subplots()
# Plot interpolated lines.
interpolated_df.plot.line(
    ax=ax,
    # Turn of `legend` to avoid duplication.
    legend=False,
)
# Plot non-interpolated points.
filtered_df[cols_to_plot].plot(
    ax=ax,
    linestyle = "-",
    marker = "o",
    # Use `TABLEAU_COLORS` to use same colors.
    color=TABLEAU_COLORS.values(),
)

Спасибо!, да, точки соединяет, но и новые точки добавляет, можно ли соединить существующие точки, не добавляя новых?

asi 24.05.2024 01:27

@asi Похоже, я включил все данные для пациента 244651 (IP + OP). Я отфильтровал только IP, как в вашем вопросе, и обновил код/график.

Ian Thompson 24.05.2024 16:24
Ответ принят как подходящий

Вы можете заменить код создания графика следующим:

# Plot all biomarkers
plt.figure(figsize=(12, 8))

# Loop through each biomarker column to plot each one separately
for column in filtered_df.columns:
    if column not in ['PatientID', 'LocationType']:
        biomarker = filtered_df[column].dropna()
        plt.plot(biomarker.index, biomarker, 'o-', label=column)

plt.title('Biomarkers by Date for Patient ID 244651 (IP Location Type)')
plt.xlabel('Date')
plt.ylabel('Biomarker Value')
plt.legend()
plt.grid(True)
plt.xticks(rotation=45)
plt.show()

Альтернативно вы можете использовать seaborn:

import seaborn as sns

# Plot all biomarkers
plt.figure(figsize=(12, 8))
sns.lineplot(data = filtered_df[['Biomarker1', 'Biomarker2', 'Biomarker3']],
             markers=['o', 'o', 'o'],
             dashes=False
             )

plt.title('Biomarkers by Date for Patient ID 244651 (IP Location Type)')
plt.ylabel('Biomarker Value')
plt.grid(True)
plt.xticks(rotation=45)
plt.show()

В любом случае сюжет выглядит следующим образом:

Другие вопросы по теме