Comment trouver les lignes contenant plus de n éléments positifs en Python avec NumPy ?

Introduction

Lorsqu’on travaille avec des données numériques en Python, il est très courant d’appliquer des conditions ligne par ligne sur des tableaux. Une tâche fréquente consiste à identifier les lignes qui contiennent plus d’un certain nombre de valeurs positives.

Ce type d’opération apparaît souvent dans :

  • Le calcul scientifique
  • La télédétection et l’analyse de données géophysiques
  • L’ingénierie de variables pour l’apprentissage automatique
  • Le contrôle qualité et le filtrage de grands jeux de données

Dans cet article, nous allons présenter une solution propre et efficace basée sur NumPy, expliquer son fonctionnement étape par étape et discuter de quelques variantes utiles.

Énoncé du problème

Étant donné un tableau NumPy 2D, nous souhaitons :

Trouver les indices des lignes qui contiennent plus de n éléments strictement supérieurs à 0

Données d’exemple

Commençons par un exemple simple :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import numpy as np

# Tableau d'exemple
arr = np.array([
    [0,  2,  3, -1],
    [4, -5,  6,  0],
    [-2, -3, -4, -5],
    [7,  8,  9, 10]
])

# Seuil
n = 2

Visuellement, ce tableau ressemble à :

Indice de ligne Valeurs
0 0, 2, 3, -1
1 4, -5, 6, 0
2 -2, -3, -4, -5
3 7, 8, 9, 10

Étape 1 : compter les éléments positifs par ligne

NumPy permet d’appliquer directement des conditions booléennes aux tableaux.

L’expression arr > 0 renvoie un tableau booléen de même forme :

1
arr > 0

Sortie :

1
2
3
4
[[False  True  True False]
 [ True False  True False]
 [False False False False]
 [ True  True  True  True]]

En NumPy :

  • True est interprété comme 1
  • False est interprété comme 0

Nous pouvons donc compter le nombre de valeurs positives dans chaque ligne à l’aide de np.sum le long de l’axe 1 :

1
2
count_positive = np.sum(arr > 0, axis=1)
print(count_positive)

Sortie :

1
[2 2 0 4]

Chaque valeur correspond au nombre d’éléments positifs dans une ligne.

Étape 2 : sélectionner les lignes ayant plus de n valeurs positives

Maintenant que nous disposons d’un comptage par ligne, le filtrage devient simple :

1
rows = np.where(count_positive > n)[0]
  • count_positive > n crée un masque booléen
  • np.where(...) renvoie les indices pour lesquels la condition est True
  • [0] extrait le tableau des indices de lignes

Affichons le résultat :

1
print("Rows with more than", n, "positive elements:", rows)

Sortie :

1
Rows with more than 2 positive elements: [3]

Seule la ligne 3 contient plus de 2 valeurs positives.

Exemple complet fonctionnel

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import numpy as np

arr = np.array([
    [0, 2, 3, -1],
    [4, -5, 6, 0],
    [-2, -3, -4, -5],
    [7, 8, 9, 10]
])

n = 2

count_positive = np.sum(arr > 0, axis=1)
rows = np.where(count_positive > n)[0]

print("Rows with more than", n, "positive elements:", rows)

Variantes courantes

1. Récupérer directement les lignes (et pas seulement leurs indices)

1
2
selected_rows = arr[count_positive > n]
print(selected_rows)

Sortie :

1
[[ 7  8  9 10]]

2. Utiliser >= n au lieu de > n

Si vous souhaitez sélectionner les lignes ayant au moins n valeurs positives :

1
rows = np.where(count_positive >= n)[0]

3. Compter les valeurs au-dessus d’un seuil quelconque

Vous n’êtes pas limité à > 0. Par exemple, pour des valeurs supérieures à 5 :

1
count_above_5 = np.sum(arr > 5, axis=1)

4. Utiliser uniquement un masque booléen (sans np.where)

Si vous préférez un style plus compact :

1
2
mask = count_positive > n
rows = np.flatnonzero(mask)

Pourquoi cette approche est efficace

  • Entièrement vectorisée (aucune boucle Python)
  • Passe à l’échelle efficacement pour de grands tableaux
  • Facile à lire et à modifier
  • Exploite le backend C optimisé de NumPy

Cela en fait une méthode idéale pour les grands jeux de données scientifiques ou satellitaires, où la performance est cruciale.

Exemple d’application : identification de détections de feux VIIRS erronées

Cette approche de seuillage ligne par ligne peut être appliquée aux produits opérationnels de détection de feux satellitaires afin d’identifier des détections erronées associées à des anomalies instrumentales ou de traitement. De telles anomalies ont été observées durant la phase initiale de la mission Suomi NPP Visible Infrared Imaging Radiometer Suite (VIIRS) et sont documentées dans Active fires from the Suomi NPP Visible Infrared Imaging Radiometer Suite: Product status and first evaluation results.

Comment trouver les lignes contenant plus de n éléments positifs en Python avec NumPy ?
Comment trouver les lignes contenant plus de n éléments positifs en Python avec NumPy ?

Les artefacts observés en début de mission incluaient des taux élevés de fausses alertes dus à des incertitudes de calibration, au striage des détecteurs, aux effets de géométrie de balayage et à une contamination résiduelle liée à l’effet « bow-tie ». Ces effets peuvent conduire à des détections de feux caractérisées par plusieurs anomalies simultanées plutôt que par un indicateur isolé.

Cadre méthodologique

Supposons que chaque détection de feu (ou pixel/cluster de feu agrégé) soit représentée par un vecteur d’indicateurs diagnostiques dérivés du produit VIIRS Active Fire et d’informations auxiliaires, par exemple :

  • Valeurs aberrantes de la puissance radiative du feu (FRP)
  • Résidus de température de brillance
  • Indicateurs de confiance ou de qualité
  • Métriques de persistance temporelle ou de cohérence spatiale

Les détections erronées sont censées présenter des dépassements simultanés sur plusieurs diagnostics. Ce comportement peut être exploité en comptant, pour chaque détection, le nombre d’indicateurs dépassant des seuils prédéfinis.

Exemple illustratif

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# Les lignes représentent des détections de feux VIIRS individuelles
# Les colonnes représentent des indicateurs diagnostiques seuillés

features = np.array([
    [0, 1, 1, 0],
    [1, 0, 1, 0],
    [0, 0, 0, 0],
    [1, 1, 1, 1]
])

n = 2  # nombre minimal d'indicateurs anormaux

anomaly_count = np.sum(features > 0, axis=1)
suspect_rows = np.where(anomaly_count > n)[0]

print("Potential spurious detections:", suspect_rows)

Cette procédure permet de signaler les détections présentant plus de n indicateurs anormaux, lesquelles peuvent ensuite faire l’objet d’analyses complémentaires ou être exclues des traitements ultérieurs.

Références

Image

of