> For the complete documentation index, see [llms.txt](https://cleyrop.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cleyrop.gitbook.io/docs/projet-data-and-ia/dataflow/creer-un-dataflow/ecrire-une-transformation.md).

# Écrire une transformation

Une transformation correspond à une étape de traitement dans un Dataflow.

Elle prend en entrée un ou plusieurs datasets, applique un code ou une règle, puis produit un nouveau dataset (ou un résultat temporaire).

Cleyrop propose plusieurs modes de transformation selon le type de Dataflow choisi : Spark, Python, SQL ou Low Code.

***

## Écrire une transformation Spark

### Transformation PySpark

Les transformations Spark sont conçues pour les traitements distribués sur de grands volumes. Elles s’exécutent sur un cluster Spark (driver + exécuteurs) **géré par Cleyrop**.

Elles s’exécutent sur un cluster Spark, avec parallélisation automatique des calculs.

{% hint style="warning" %}

* `cleyrop_datasets["projet.nom_dataset"]` **renvoie un DataFrame&#x20;*****pandas-on-Spark*** (`pyspark.pandas.DataFrame`).
* **Aucune SparkSession à créer** : l’initialisation et la configuration sont entièrement gérées par Cleyrop.
* Vous devez impérativement **retourner un DataFrame** (Spark ou pandas-on-Spark) à l'issue de la transformation
  {% endhint %}

{% hint style="success" %}
Vous pouvez [**Accèder aux Données de travail**](/docs/projet-data-and-ia/donnees-de-travail-fichiers/utiliser-les-donnees-dans-un-script.md#utiliser-dans-le-dataflow) dans une transformation PySpark
{% endhint %}

L’**auto-complétion** aide à insérer la bonne syntaxe : tapez au moins trois lettres du nom d’un Dataset dans l’éditeur.

**Exemple :**

{% code title="pyspark transformation" %}

```python
voitures = cleyrop_datasets["projet.voitures"]
voitures_modifiees = voitures.with_column("prix", voitures["prix"] * 1.2)
return voitures_modifiees
```

{% endcode %}

Le code doit retourner un DataFrame Spark (pyspark.pandas.DataFrame ou DataFrame).

**Conversion en Dataframe Spark**

Dans certains cas (APIs Spark non disponibles en pandas-on-Spark, usages MLlib, fonctions SQL avancées), convertissez en Spark DataFrame :

{% code title="spark dataframe conversion" %}

```python
voitures_pos = cleyrop_datasets["projet.voitures"]          # pandas-on-Spark
voitures_spark = voitures_pos.to_spark()                    # Spark DataFrame
from pyspark.sql import functions as F
res = voitures_spark.withColumn("prix", F.col("prix") * 1.2)
return res                           # retour en pandas-on-Spark
```

{% endcode %}

💡 Si vous convertissez en Spark DataFrame, Cleyrop gère automatiquement le passage du résultat vers le dataset de sortie.

#### Points d’attention

* **Évitez `to_pandas()`**, qui rapatrie les données sur le driver → **risque d’OOM**.
* Si vous utilisez `to_spark()`, veillez à retourner le Spark DataFrame, pas un objet transformé localement.
* Ne retournez jamais de list, dict ou autre type Python brut lorsque la transformation alimente un dataset de sortie.
* Conservez une logique “distribuée” : pas de boucles Python sur des millions de lignes.

### Transformation SQL

Les transformations SQL permettent d’exécuter directement du code Spark SQL sur les datasets d’entrée (Dataflows Spark uniquement).

{% code title="SQL transformation" %}

```sql
SELECT modele, prix * 1.2 AS prix
FROM projet.voitures
WHERE pays = 'France'
```

{% endcode %}

Le dataset d’entrée est reconnu sous son Identifiant Unique (projet.nom\_du\_dataset).

### Transformation Low Code

Le [mode Low Code](/docs/projet-data-and-ia/dataflow/transformer-sans-code-low-code.md) permet de créer des transformations visuelles sans écrire de code.

Chaque bloc correspond à une opération (filtrer, joindre, agréger, renommer, etc.).

Les transformations Low Code peuvent être combinées avec du Python ou du SQL.

***

## Écrire une transformation Python (Polars)

Les transformations Python s’exécutent sur un cluster Python dédié, idéal pour :

* les traitements légers,
* les automatisations,
* les appels API ou opérations métier

{% hint style="warning" %}

* `cleyrop_datasets["projet.nom_dataset"]` **renvoie un polars LazyFrame**
* Si la transformation a un dataset de sortie, le code doit impérativement retourner un objet **Polars LazyFrame** (recommandé) ou un Pandas DataFrame.
* Utilisez **Pandas** **uniquement pour des bibliothèques non compatibles Polars**.
  {% endhint %}

{% hint style="success" %}
Vous pouvez utiliser la [**librairie PyAi**](/docs/la-fabrique/deployer-des-apps-et-des-tools.md#utiliser-la-librairie-de-composants-cleyrop) **dans les clusters Python 3.11 et 3.12.**

Vous pouvez [**Accèder aux Données de travail**](/docs/projet-data-and-ia/donnees-de-travail-fichiers/utiliser-les-donnees-dans-un-script.md#utiliser-dans-le-dataflow) dans une transformation python
{% endhint %}

Exemple :

{% code title="python transformation " %}

```python
import polars as pl
voitures = cleyrop_datasets["projet.voitures"]  # LazyFrame Polars
voitures_modifiees = voitures.with_columns((pl.col("prix") * 1.2).alias("prix"))
return voitures_modifiees
```

{% endcode %}

#### Pourquoi utiliser Polars ?

💡 Par défaut, Cleyrop exécute les Dataflows Python en Polars (LazyFrame).

Polars est la librairie moderne et performante recommandée par Cleyrop. Elle combine vitesse, sécurité et lazy computation.

* Performante : parallélisation native (multicore).
* Économe en mémoire : calcul différé, pas de chargement complet.
* Lazy execution : Cleyrop peut optimiser automatiquement les traitements chaînés.
* Interopérable : conversions simples vers Pandas si nécessaire.

***

{% hint style="warning" %}
**Suppression d'un nœud de transformation** : après avoir supprimé un nœud, sauvegardez le Dataflow avant d'en recréer un nouveau. Si vous créez une transformation portant le même nom qu'un nœud récemment supprimé sans avoir sauvegardé au préalable, un conflit peut empêcher son bon fonctionnement.
{% endhint %}

## Utiliser les variables d’environnement

Vous pouvez déclarer des [**variables d’environnement** ](/docs/projet-data-and-ia/dataflow.md#ajouter-une-variable-denvironnement)(ex. API\_KEY, S3\_PATH) accessibles directement dans vos transformations :

```python
import os

api_key = os.getenv("API_KEY")

print(f"Clé API : {api_key}")
```

#### Variables globales et locales

* **Globales** : créées dans la branche principale (main), accessibles dans toutes les branches.
* **Locales** : propres à une branche, elles masquent les variables globales de même nom.
* Lorsqu’une variable locale et une variable globale portent le même nom, la locale est prioritaire lors de l’exécution dans la branche correspondante.

***

## Bonnes pratiques

* Définissez des variables locales dans la branche main si vous souhaitez empêcher l’utilisation accidentelle de variables de production.
* Évitez de coder en dur des valeurs sensibles dans vos transformations.
* Pour tester un Dataflow sur des environnements différents (ex. sandbox vs prod), changez simplement la valeur de la variable sans modifier le code.
