# Timemesh 🕰️
[](https://www.python.org/)
[](https://pypi.org/project/timemesh/)
A Python library for efficient time series data preprocessing and windowing for machine learning.
## Features
- 🚀 **Flexible Windowing**: Create overlapping/non-overlapping windows with configurable time steps (T) and horizon (H)
- 📊 **Normalization**: Supports Min-Max and Z-score normalization
- 🔄 **Denormalization**: Revert normalized data back to original scale
- 🧩 **Modular Design**: Separate data loading and normalization logic
- ✅ **Validation**: Built-in data integrity checks
## Installation
```bash
pip install timemesh
```
## Quick Start
```
import timemesh as tm
# Initialize data loader
loader = tm.DataLoader(
T=24, # Use 24 historical steps
H=6, # Predict 6 steps ahead
input_cols=["temperature", "humidity"],
output_cols=["target_feature"],
norm="MM" # Min-Max normalization
)
# Load and preprocess data
X, Y, input_params, output_params = loader.load_csv("data.csv")
```
| Parameter | Description | Default | Options |
|---------------|--------------------------------------|---------|-----------------------|
| **T** | Historical time steps per sample | 1 | Any positive integer |
| **H** | Prediction horizon steps | 1 | Any positive integer |
| **input_cols**| Features used for model input | None(All will be input) | List of column names |
| **output_cols**| Target features for prediction | None(All Will be output | List of column names |
| **norm** | Normalization method | `None`(No Normalization) | `"MM"`, `"Z"` |
| **steps** | Step size between windows | `None`(Non overlapping) | Any positive integer |
## Example Code
Download Example dataset
```
wget https://github.com/L-A-Sandhu/TimeMesh/blob/main/examples/data.csv
```
#### Example Usage Code
```
import timemesh as tm
import numpy as np
import pandas as pd
# =================================================================
# Load your data for verification
# =================================================================
df = pd.read_csv("data.csv")
input_cols = ["C_WD50M", "C_WS50M", "C_PS", "C_T2M", "C_QV2M", "N_WD50M", "N_WS50M", "N_PS", "N_T2M", "N_QV2M"]
output_cols = ["C_WS50M", "N_WS50M", "S_WS50M", "E_WS50M", "W_WS50M"]
# =================================================================
# Case 1: Without Normalization (norm=None)
# =================================================================
print("\n--- Case 1: Without Normalization ---")
loader_raw = tm.DataLoader(T=24, H=6, input_cols=input_cols, output_cols=output_cols, norm=None)
X_raw, Y_raw = loader_raw.load_csv("data.csv")
print("\nLoaded raw data:")
print(f"Shape of X_raw: {X_raw.shape}")
print(f"Shape of Y_raw: {Y_raw.shape}")
print(f"First sample of X_raw:\n{X_raw[0]}")
print(f"First sample of Y_raw:\n{Y_raw[0]}")
# =================================================================
# Case 2: With Min-Max Normalization
# =================================================================
print("\n--- Case 2: With Min-Max Normalization ---")
loader_norm = tm.DataLoader(T=24, H=6, input_cols=input_cols, output_cols=output_cols, norm="MM")
X_norm, Y_norm, input_params, output_params = loader_norm.load_csv("data.csv")
print("\nLoaded normalized data:")
print(f"Shape of X_norm: {X_norm.shape}")
print(f"Shape of Y_norm: {Y_norm.shape}")
print(f"Normalization parameters (input):\n{input_params}")
print(f"Normalization parameters (output):\n{output_params}")
print(f"First sample of X_norm:\n{X_norm[0]}")
print(f"First sample of Y_norm:\n{Y_norm[0]}")
# =================================================================
# Denormalize the normalized data
# =================================================================
print("\n--- Denormalizing the normalized data ---")
X_denorm = tm.Normalizer.denormalize(
X_norm, params=input_params, method="MM", feature_order=input_cols # Must match original order
)
Y_denorm = tm.Normalizer.denormalize(Y_norm, params=output_params, method="MM", feature_order=output_cols)
print("\nDenormalized data:")
print(f"Shape of X_denorm: {X_denorm.shape}")
print(f"Shape of Y_denorm: {Y_denorm.shape}")
print(f"First sample of X_denorm:\n{X_denorm[0]}")
print(f"First sample of Y_denorm:\n{Y_denorm[0]}")
# =================================================================
# Verification Checks
# =================================================================
def verify_results():
print("\n--- Verification Results ---")
# Check 1: Raw vs Denormalized should match exactly
x_match = np.allclose(X_raw, X_denorm, atol=1e-4)
y_match = np.allclose(Y_raw, Y_denorm, atol=1e-4)
print(f"X Match (Raw vs Denorm): {x_match}")
print(f"Y Match (Raw vs Denorm): {y_match}")
# Check 2: Normalized vs Raw ranges
print("\nNormalization Ranges:")
print(f"X_norm range: [{X_norm.min():.2f}, {X_norm.max():.2f}]")
print(f"Y_norm range: [{Y_norm.min():.2f}, {Y_norm.max():.2f}]")
# Check 3: Sample value comparison
sample_idx = 0 # First sample
time_idx = 0 # First timestep
feature_idx = 1 # C_WS50M
print("\nSample Value Comparison:")
print(f"Original (Raw): {X_raw[sample_idx, time_idx, feature_idx]:.2f}")
print(f"Denormalized: {X_denorm[sample_idx, time_idx, feature_idx]:.2f}")
print(f"Normalized: {X_norm[sample_idx, time_idx, feature_idx]:.2f}")
verify_results()
# =================================================================
# Case 3: Test with norm=None (No normalization)
# =================================================================
def test_no_normalization():
print("\n--- Case 3: Test with No Normalization ---")
loader = tm.DataLoader(T=24, H=6, input_cols=input_cols, output_cols=output_cols, norm=None)
X, Y = loader.load_csv("data.csv")
# Directly compare with raw data from CSV
expected_X = df[input_cols].values[:24] # First window
assert np.allclose(X[0], expected_X), "No normalization should return raw data"
print("\nTest Passed: No normalization returns raw data successfully.")
test_no_normalization()
# =================================================================
# Case 4: With Z-Score Normalization
# =================================================================
print("\n--- Case 4: With Z-Score Normalization ---")
loader_z = tm.DataLoader(T=24, H=6, input_cols=input_cols, output_cols=output_cols, norm="Z") # Z-score normalization
X_norm_z, Y_norm_z, input_params_z, output_params_z = loader_z.load_csv("data.csv")
print("\nLoaded Z-normalized data:")
print(f"Shape of X_norm_z: {X_norm_z.shape}")
print(f"Shape of Y_norm_z: {Y_norm_z.shape}")
print(f"Z-score Normalization parameters (input):\n{input_params_z}")
print(f"Z-score Normalization parameters (output):\n{output_params_z}")
print(f"First sample of X_norm_z:\n{X_norm_z[0]}")
print(f"First sample of Y_norm_z:\n{Y_norm_z[0]}")
# =================================================================
# Denormalize the Z-normalized data
# =================================================================
print("\n--- Denormalizing the Z-normalized data ---")
X_denorm_z = tm.Normalizer.denormalize(X_norm_z, params=input_params_z, method="Z", feature_order=input_cols)
Y_denorm_z = tm.Normalizer.denormalize(Y_norm_z, params=output_params_z, method="Z", feature_order=output_cols)
print("\nDenormalized Z-data:")
print(f"Shape of X_denorm_z: {X_denorm_z.shape}")
print(f"Shape of Y_denorm_z: {Y_denorm_z.shape}")
print(f"First sample of X_denorm_z:\n{X_denorm_z[0]}")
print(f"First sample of Y_denorm_z:\n{Y_denorm_z[0]}")
# =================================================================
# Z-Score Specific Verification
# =================================================================
def verify_zscore_results():
print("\n--- Z-Score Specific Verification Results ---")
# 1. Check reconstruction accuracy
x_match = np.allclose(X_raw, X_denorm_z, atol=1e-4)
y_match = np.allclose(Y_raw, Y_denorm_z, atol=1e-4)
print(f"X Match (Raw vs Denorm-Z): {x_match}")
print(f"Y Match (Raw vs Denorm-Z): {y_match}")
# 2. Check Z-score properties
X_flat_z = X_norm_z.reshape(-1, len(input_cols))
print("\nZ-Score Statistics (Input Features):")
for i, col in enumerate(input_cols):
print(f"{col}:")
print(f" Mean ≈ {X_flat_z[:, i].mean():.2f} (should be ~0)")
print(f" Std ≈ {X_flat_z[:, i].std():.2f} (should be ~1)")
# 3. Sample value comparison
sample_idx = 0
time_idx = 0
feature_idx = 1 # C_WS50M
original_value = X_raw[sample_idx, time_idx, feature_idx]
normalized_value = X_norm_z[sample_idx, time_idx, feature_idx]
params = input_params_z[input_cols[feature_idx]]
print("\nSample Value Breakdown (C_WS50M):")
print(f"Original value: {original_value:.2f}")
print(f"Normalized: ({original_value:.2f} - {params['mean']:.2f}) / {params['std']:.2f} = {normalized_value:.2f}")
print(
f"Denormalized: ({normalized_value:.2f} * {params['std']:.2f}) + {params['mean']:.2f} = {X_denorm_z[sample_idx, time_idx, feature_idx]:.2f}"
)
verify_zscore_results()
# =================================================================
# Summary
# =================================================================
print("\n--- Summary ---")
print("This script has successfully run the following cases:")
print("1. Loaded raw data without normalization.")
print("2. Loaded and normalized data with Min-Max normalization.")
print("3. Denormalized the data back to the raw scale.")
print("4. Verified that the denormalized data matches the original raw data.")
print("5. Tested the case with no normalization and compared the raw data.")
print("6. Loaded and verified Z-score normalization and denormalization.")
```
Raw data
{
"_id": null,
"home_page": "https://github.com/L-A-Sandhu/timemesh",
"name": "timemesh",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.12",
"maintainer_email": null,
"keywords": "time-series, machine learning, data preprocessing",
"author": "Laeeq",
"author_email": "Laeeq.aslam.100@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/1b/49/32e0be41abbdbbb6e4f98f883c73185cb0db49595ea1de8571fd1872c0bd/timemesh-0.2.1.tar.gz",
"platform": null,
"description": "# Timemesh \ud83d\udd70\ufe0f\n\n[](https://www.python.org/)\n[](https://pypi.org/project/timemesh/)\n\nA Python library for efficient time series data preprocessing and windowing for machine learning.\n\n## Features\n\n- \ud83d\ude80 **Flexible Windowing**: Create overlapping/non-overlapping windows with configurable time steps (T) and horizon (H)\n- \ud83d\udcca **Normalization**: Supports Min-Max and Z-score normalization\n- \ud83d\udd04 **Denormalization**: Revert normalized data back to original scale\n- \ud83e\udde9 **Modular Design**: Separate data loading and normalization logic\n- \u2705 **Validation**: Built-in data integrity checks\n\n## Installation\n\n```bash\npip install timemesh\n```\n\n## Quick Start\n```\nimport timemesh as tm\n\n# Initialize data loader\nloader = tm.DataLoader(\n T=24, # Use 24 historical steps\n H=6, # Predict 6 steps ahead\n input_cols=[\"temperature\", \"humidity\"],\n output_cols=[\"target_feature\"],\n norm=\"MM\" # Min-Max normalization\n)\n\n# Load and preprocess data\nX, Y, input_params, output_params = loader.load_csv(\"data.csv\")\n```\n| Parameter | Description | Default | Options |\n|---------------|--------------------------------------|---------|-----------------------|\n| **T** | Historical time steps per sample | 1 | Any positive integer |\n| **H** | Prediction horizon steps | 1 | Any positive integer |\n| **input_cols**| Features used for model input | None(All will be input) | List of column names |\n| **output_cols**| Target features for prediction | None(All Will be output | List of column names |\n| **norm** | Normalization method | `None`(No Normalization) | `\"MM\"`, `\"Z\"` |\n| **steps** | Step size between windows | `None`(Non overlapping) | Any positive integer |\n\n\n\n## Example Code \nDownload Example dataset \n```\nwget https://github.com/L-A-Sandhu/TimeMesh/blob/main/examples/data.csv\n```\n#### Example Usage Code \n```\nimport timemesh as tm\nimport numpy as np\nimport pandas as pd\n\n# =================================================================\n# Load your data for verification\n# =================================================================\ndf = pd.read_csv(\"data.csv\")\ninput_cols = [\"C_WD50M\", \"C_WS50M\", \"C_PS\", \"C_T2M\", \"C_QV2M\", \"N_WD50M\", \"N_WS50M\", \"N_PS\", \"N_T2M\", \"N_QV2M\"]\noutput_cols = [\"C_WS50M\", \"N_WS50M\", \"S_WS50M\", \"E_WS50M\", \"W_WS50M\"]\n\n# =================================================================\n# Case 1: Without Normalization (norm=None)\n# =================================================================\nprint(\"\\n--- Case 1: Without Normalization ---\")\nloader_raw = tm.DataLoader(T=24, H=6, input_cols=input_cols, output_cols=output_cols, norm=None)\nX_raw, Y_raw = loader_raw.load_csv(\"data.csv\")\n\nprint(\"\\nLoaded raw data:\")\nprint(f\"Shape of X_raw: {X_raw.shape}\")\nprint(f\"Shape of Y_raw: {Y_raw.shape}\")\nprint(f\"First sample of X_raw:\\n{X_raw[0]}\")\nprint(f\"First sample of Y_raw:\\n{Y_raw[0]}\")\n\n# =================================================================\n# Case 2: With Min-Max Normalization\n# =================================================================\nprint(\"\\n--- Case 2: With Min-Max Normalization ---\")\nloader_norm = tm.DataLoader(T=24, H=6, input_cols=input_cols, output_cols=output_cols, norm=\"MM\")\nX_norm, Y_norm, input_params, output_params = loader_norm.load_csv(\"data.csv\")\n\nprint(\"\\nLoaded normalized data:\")\nprint(f\"Shape of X_norm: {X_norm.shape}\")\nprint(f\"Shape of Y_norm: {Y_norm.shape}\")\nprint(f\"Normalization parameters (input):\\n{input_params}\")\nprint(f\"Normalization parameters (output):\\n{output_params}\")\nprint(f\"First sample of X_norm:\\n{X_norm[0]}\")\nprint(f\"First sample of Y_norm:\\n{Y_norm[0]}\")\n\n# =================================================================\n# Denormalize the normalized data\n# =================================================================\nprint(\"\\n--- Denormalizing the normalized data ---\")\nX_denorm = tm.Normalizer.denormalize(\n X_norm, params=input_params, method=\"MM\", feature_order=input_cols # Must match original order\n)\n\nY_denorm = tm.Normalizer.denormalize(Y_norm, params=output_params, method=\"MM\", feature_order=output_cols)\n\nprint(\"\\nDenormalized data:\")\nprint(f\"Shape of X_denorm: {X_denorm.shape}\")\nprint(f\"Shape of Y_denorm: {Y_denorm.shape}\")\nprint(f\"First sample of X_denorm:\\n{X_denorm[0]}\")\nprint(f\"First sample of Y_denorm:\\n{Y_denorm[0]}\")\n\n# =================================================================\n# Verification Checks\n# =================================================================\ndef verify_results():\n print(\"\\n--- Verification Results ---\")\n\n # Check 1: Raw vs Denormalized should match exactly\n x_match = np.allclose(X_raw, X_denorm, atol=1e-4)\n y_match = np.allclose(Y_raw, Y_denorm, atol=1e-4)\n\n print(f\"X Match (Raw vs Denorm): {x_match}\")\n print(f\"Y Match (Raw vs Denorm): {y_match}\")\n\n # Check 2: Normalized vs Raw ranges\n print(\"\\nNormalization Ranges:\")\n print(f\"X_norm range: [{X_norm.min():.2f}, {X_norm.max():.2f}]\")\n print(f\"Y_norm range: [{Y_norm.min():.2f}, {Y_norm.max():.2f}]\")\n\n # Check 3: Sample value comparison\n sample_idx = 0 # First sample\n time_idx = 0 # First timestep\n feature_idx = 1 # C_WS50M\n\n print(\"\\nSample Value Comparison:\")\n print(f\"Original (Raw): {X_raw[sample_idx, time_idx, feature_idx]:.2f}\")\n print(f\"Denormalized: {X_denorm[sample_idx, time_idx, feature_idx]:.2f}\")\n print(f\"Normalized: {X_norm[sample_idx, time_idx, feature_idx]:.2f}\")\n\nverify_results()\n\n# =================================================================\n# Case 3: Test with norm=None (No normalization)\n# =================================================================\ndef test_no_normalization():\n print(\"\\n--- Case 3: Test with No Normalization ---\")\n loader = tm.DataLoader(T=24, H=6, input_cols=input_cols, output_cols=output_cols, norm=None)\n X, Y = loader.load_csv(\"data.csv\")\n\n # Directly compare with raw data from CSV\n expected_X = df[input_cols].values[:24] # First window\n assert np.allclose(X[0], expected_X), \"No normalization should return raw data\"\n \n print(\"\\nTest Passed: No normalization returns raw data successfully.\")\n\ntest_no_normalization()\n\n# =================================================================\n# Case 4: With Z-Score Normalization\n# =================================================================\nprint(\"\\n--- Case 4: With Z-Score Normalization ---\")\nloader_z = tm.DataLoader(T=24, H=6, input_cols=input_cols, output_cols=output_cols, norm=\"Z\") # Z-score normalization\nX_norm_z, Y_norm_z, input_params_z, output_params_z = loader_z.load_csv(\"data.csv\")\n\nprint(\"\\nLoaded Z-normalized data:\")\nprint(f\"Shape of X_norm_z: {X_norm_z.shape}\")\nprint(f\"Shape of Y_norm_z: {Y_norm_z.shape}\")\nprint(f\"Z-score Normalization parameters (input):\\n{input_params_z}\")\nprint(f\"Z-score Normalization parameters (output):\\n{output_params_z}\")\nprint(f\"First sample of X_norm_z:\\n{X_norm_z[0]}\")\nprint(f\"First sample of Y_norm_z:\\n{Y_norm_z[0]}\")\n\n# =================================================================\n# Denormalize the Z-normalized data\n# =================================================================\nprint(\"\\n--- Denormalizing the Z-normalized data ---\")\nX_denorm_z = tm.Normalizer.denormalize(X_norm_z, params=input_params_z, method=\"Z\", feature_order=input_cols)\nY_denorm_z = tm.Normalizer.denormalize(Y_norm_z, params=output_params_z, method=\"Z\", feature_order=output_cols)\n\nprint(\"\\nDenormalized Z-data:\")\nprint(f\"Shape of X_denorm_z: {X_denorm_z.shape}\")\nprint(f\"Shape of Y_denorm_z: {Y_denorm_z.shape}\")\nprint(f\"First sample of X_denorm_z:\\n{X_denorm_z[0]}\")\nprint(f\"First sample of Y_denorm_z:\\n{Y_denorm_z[0]}\")\n\n# =================================================================\n# Z-Score Specific Verification\n# =================================================================\ndef verify_zscore_results():\n print(\"\\n--- Z-Score Specific Verification Results ---\")\n\n # 1. Check reconstruction accuracy\n x_match = np.allclose(X_raw, X_denorm_z, atol=1e-4)\n y_match = np.allclose(Y_raw, Y_denorm_z, atol=1e-4)\n\n print(f\"X Match (Raw vs Denorm-Z): {x_match}\")\n print(f\"Y Match (Raw vs Denorm-Z): {y_match}\")\n\n # 2. Check Z-score properties\n X_flat_z = X_norm_z.reshape(-1, len(input_cols))\n print(\"\\nZ-Score Statistics (Input Features):\")\n for i, col in enumerate(input_cols):\n print(f\"{col}:\")\n print(f\" Mean \u2248 {X_flat_z[:, i].mean():.2f} (should be ~0)\")\n print(f\" Std \u2248 {X_flat_z[:, i].std():.2f} (should be ~1)\")\n\n # 3. Sample value comparison\n sample_idx = 0\n time_idx = 0\n feature_idx = 1 # C_WS50M\n\n original_value = X_raw[sample_idx, time_idx, feature_idx]\n normalized_value = X_norm_z[sample_idx, time_idx, feature_idx]\n params = input_params_z[input_cols[feature_idx]]\n\n print(\"\\nSample Value Breakdown (C_WS50M):\")\n print(f\"Original value: {original_value:.2f}\")\n print(f\"Normalized: ({original_value:.2f} - {params['mean']:.2f}) / {params['std']:.2f} = {normalized_value:.2f}\")\n print(\n f\"Denormalized: ({normalized_value:.2f} * {params['std']:.2f}) + {params['mean']:.2f} = {X_denorm_z[sample_idx, time_idx, feature_idx]:.2f}\"\n )\n\nverify_zscore_results()\n\n# =================================================================\n# Summary\n# =================================================================\nprint(\"\\n--- Summary ---\")\nprint(\"This script has successfully run the following cases:\")\nprint(\"1. Loaded raw data without normalization.\")\nprint(\"2. Loaded and normalized data with Min-Max normalization.\")\nprint(\"3. Denormalized the data back to the raw scale.\")\nprint(\"4. Verified that the denormalized data matches the original raw data.\")\nprint(\"5. Tested the case with no normalization and compared the raw data.\")\nprint(\"6. Loaded and verified Z-score normalization and denormalization.\")\n\n```\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Spatio-temporal data preparation toolkit",
"version": "0.2.1",
"project_urls": {
"Documentation": "https://github.com/L-A-Sandhu/timemesh/blob/main/README.md",
"Homepage": "https://github.com/L-A-Sandhu/timemesh",
"Repository": "https://github.com/L-A-Sandhu/timemesh"
},
"split_keywords": [
"time-series",
" machine learning",
" data preprocessing"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "f7643b22aaa4dc9b72f9a294fabd2b2cafaaab168ca3def2b41fcdf76c037045",
"md5": "808fec77062c861bf8c521a09a1c545f",
"sha256": "de789e252537d9eefa22a02818bc42e880cf7a2655bf78482cff71995caf221c"
},
"downloads": -1,
"filename": "timemesh-0.2.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "808fec77062c861bf8c521a09a1c545f",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.12",
"size": 6509,
"upload_time": "2025-03-06T00:54:37",
"upload_time_iso_8601": "2025-03-06T00:54:37.288539Z",
"url": "https://files.pythonhosted.org/packages/f7/64/3b22aaa4dc9b72f9a294fabd2b2cafaaab168ca3def2b41fcdf76c037045/timemesh-0.2.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "1b4932e0be41abbdbbb6e4f98f883c73185cb0db49595ea1de8571fd1872c0bd",
"md5": "e1282b97c4af3116fcb5aea78e0897a5",
"sha256": "282994e826702c9b11d396da672d4902de289a37611c7869397a559a97522a27"
},
"downloads": -1,
"filename": "timemesh-0.2.1.tar.gz",
"has_sig": false,
"md5_digest": "e1282b97c4af3116fcb5aea78e0897a5",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.12",
"size": 5554,
"upload_time": "2025-03-06T00:54:39",
"upload_time_iso_8601": "2025-03-06T00:54:39.214220Z",
"url": "https://files.pythonhosted.org/packages/1b/49/32e0be41abbdbbb6e4f98f883c73185cb0db49595ea1de8571fd1872c0bd/timemesh-0.2.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-03-06 00:54:39",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "L-A-Sandhu",
"github_project": "timemesh",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "timemesh"
}