[Python] On making a time series heat map

Discussão em 'Python' iniciado por Stack, Março 28, 2025.

  1. Stack

    Stack Membro Participativo

    In relation this post, I have acquired the raw disdrometer data which includes multiple pairs of Drop Size (0.062 mm, 0.187 mm etc) and Counts of raindrops (32 bins). I would like to create a time series heatmap of the disdrometer data in which the independent variables are Time and Drop Size, while the dependent variable is "log N(d)".

    How can I efficiently create this heatmap time series in Python? I did try to do this with the initial code, but I didn't manage to reproduce the sample figure in the previous post, correctly (the visualization). is there a way to adjust the x and y limits, the x and y tickmarks/labels as well? (as they were quite incorrect).

    To compute for N(d), the formula we use is "Sum of Counts in each time stamp" / 0.54 * 300 * 0.125

    I did try my best to do this with the initial code, but I didn't manage to reproduce the sample figure in the previous post, correctly (the visualization). Like is there a way to adjust/correct the x and y limits? Also the tickmarks/labels in x and y axis were quite incorrect.

    The sample disdrometer data can be acquired through here. I'll appreciate a helping hand to this matter.

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

    # File paths for all datasets
    all_file_paths = {
    "0.062 mm": "07292023/0.062 mm.csv",
    "0.187 mm": "07292023/0.187 mm.csv",
    "0.312 mm": "07292023/0.312 mm.csv",
    "0.437 mm": "07292023/0.437 mm.csv",
    "0.562 mm": "07292023/0.562 mm.csv",
    "0.687 mm": "07292023/0.687 mm.csv",
    "0.812 mm": "07292023/0.812 mm.csv",
    "0.937 mm": "07292023/0.937 mm.csv",
    "1.062 mm": "07292023/1.062 mm.csv",
    "1.187 mm": "07292023/1.187 mm.csv",
    "1.375 mm": "07292023/1.375 mm.csv",
    "1.625 mm": "07292023/1.625 mm.csv",
    "1.875 mm": "07292023/1.875 mm.csv",
    "2.125 mm": "07292023/2.125 mm.csv",
    "2.375 mm": "07292023/2.375 mm.csv",
    "3.25 mm": "07292023/3.25 mm.csv",
    "3.75 mm": "07292023/3.75 mm.csv",
    "4.25 mm": "07292023/4.25 mm.csv",
    "4.75 mm": "07292023/4.75 mm.csv",
    "5.5 mm": "07292023/5.5 mm.csv",
    "6.5 mm": "07292023/6.5 mm.csv",
    "7.5 mm": "07292023/7.5 mm.csv",
    "8.5 mm": "07292023/8.5 mm.csv",
    }

    # Constants for N(D) calculation
    factor = 0.54 * 300 * 0.125

    # Read and process all datasets
    combined_data = []
    for size, path in all_file_paths.items():
    df = pd.read_csv(path)
    df["Size"] = float(size.split()[0]) # Ensure size is numeric
    time_col = df["Time stamp"] # Keep original time format
    nd_values = df.iloc[:, 2:].astype(float) / factor # Compute N(D)

    # Sum bins within 1 mm intervals
    size_bin = int(df["Size"].iloc[0] // 0.25)
    sum_nd = nd_values.sum(axis=1) # Sum all bins in this interval
    log_nd = np.log10(sum_nd.replace(0, np.nan)) # Compute log N(D)

    # Create DataFrame with relevant information
    result_df = pd.DataFrame({
    "Time stamp": time_col,
    "Size_bin": size_bin,
    "log N(D)": log_nd
    })
    combined_data.append(result_df)

    # Combine into a single DataFrame
    heatmap_data = pd.concat(combined_data).reset_index(drop=True)

    # Filter for log N(D) > 0
    #heatmap_data = heatmap_data[heatmap_data["log N(D)"] > 0]

    # Aggregate log N(D) by size bin and time
    heatmap_binned = heatmap_data.groupby(["Time stamp", "Size_bin"])['log N(D)'].mean().reset_index()

    # Pivot for heatmap
    heatmap_pivot = heatmap_binned.pivot(index="Size_bin", columns="Time stamp", values="log N(D)")

    # Plot heatmap using axes
    fig, ax = plt.subplots(figsize=(12, 6))
    sns.heatmap(heatmap_pivot, cmap="turbo", robust=True, vmin=0, vmax=2,
    ax=ax, cbar_kws={'pad': 0.1})
    ax.set_xlabel("Time Stamp (LST)", fontsize=15)
    ax.set_ylabel("Drop Size (mm)", fontsize=15)
    #ax.set_title("Raindrop Size Distribution Heatmap (Summed Bins)")
    ax.invert_yaxis() # Invert y-axis to start from lowest to highest size

    # Set y-axis tick labels to represent bin intervals
    ax.set_yticks(np.arange(0, heatmap_pivot.shape[0], 1))
    ax.set_yticklabels(np.arange(0, heatmap_pivot.shape[0], 1))

    custom_labels = np.arange(1, heatmap_pivot.shape[0] + 1)
    ax.set_yticklabels(custom_labels)

    #ax.minorticks_on()
    ax.tick_params(axis='x', which='major', labelsize=15, length=10, width=2, top=True, right=True, direction='in')
    ax.tick_params(axis='y', which='major', labelsize=15, length=10, width=2, top=True, right=True, direction='in', rotation=0)
    #ax.tick_params(which='minor', length=7, width=1.5, top=True, right=True, direction='in')

    # Customize tick parameters for colorbar
    cbar = ax.collections[0].colorbar
    cbar.set_label('log N(D)', fontsize=15)
    cbar.ax.minorticks_on()
    cbar.ax.tick_params(which='major', labelsize=15, length=10, width=2, top=True, right=True, direction='in')
    cbar.ax.tick_params(which='minor', length=5, width=1.5, top=True, right=True, direction='in')

    ax.grid(ls='--', alpha=0.35)

    # Add border to the colorbar
    cbar.outline.set_edgecolor('black')
    cbar.outline.set_linewidth(2)

    # Add border to the plot
    plt.gca().spines['top'].set_visible(True)
    plt.gca().spines['right'].set_visible(True)
    plt.gca().spines['left'].set_visible(True)
    plt.gca().spines['bottom'].set_visible(True)

    #plt.rcParams['axes.linewidth'] = 2
    #plt.rcParams['mathtext.fontset'] = 'cm'
    #plt.rcParams['mathtext.default'] = 'regular'
    #plt.rcParams['font.family'] = 'STIXGeneral'
    plt.savefig('Test1.jpg', dpi=300, bbox_inches='tight')
    plt.show()


    [​IMG]

    Continue reading...

Compartilhe esta Página