Utilisation d'iloc pour définir des valeurs [fermé]

13

Cette ligne renvoie les 4 premières lignes de la trame combinedde données pourfeature_a

combined.iloc[0:4]["feature_a"]

Comme prévu, cette ligne suivante renvoie les 2e, 4e et 16e lignes de la trame de données pour la colonne feature_a:

combined.iloc[[1,3,15]]["feature_a"]

Cette ligne définit les 4 premières lignes de la trame de données pour feature_ato 77.

combined.iloc[0:4]["feature_a"] = 77

Cette ligne fait quelque chose. Des calculs sont en cours, car cela prend plus de temps lorsqu'il est appliqué à une liste plus longue.

combined.iloc[[1,3,15]]["feature_a"] = 88

Les 2e, 4e et 16e rangées ne sont pas définies 88lorsque vérifiées avec ceci:

combined.iloc[[1,3,15]]["feature_a"]

Comment puis-je définir une liste arbitraire de lignes d'une colonne d'une trame de données sur une valeur sans prendre un détour de codage massif?

Ce scénario semble être assez simple et courant.

Doug7
la source
Il s'agit d'une question de programmation uniquement (pas de statistiques) et appartient donc à Stack Overflow
Jake Westfall
Sans un exemple reproductible minimal, ce type de question serait également hors sujet sur stackoverflow
Glen_b -Reinstate Monica

Réponses:

24

Si vous inversez les sélecteurs et sélectionnez d'abord par colonne, cela fonctionnera correctement:

Code:

df.feature_a.iloc[[1, 3, 15]] = 88

Pourquoi?

Lorsque vous avez fait la première (méthode non fonctionnelle), vous sélectionnez une section non contiguë du bloc de données. Vous devriez avoir reçu l'avertissement:

Une valeur tente d'être définie sur une copie d'une tranche d'un DataFrame. Essayez d'utiliser .loc [row_indexer, col_indexer] = value à la place

Voir les mises en garde dans la documentation: http://pandas.pydata.org/pandas- > docs / stable / indexing.html # indexing-view-versus-copy

En effet, deux opérations indépendantes ont lieu.

  1. combined.iloc[[1,3,15]]crée un nouveau cadre de données de seulement trois lignes, et le cadre est nécessairement copié. ensuite...
  2. sélectionnez une colonne via ["feature_a"]mais elle est sélectionnée par rapport à la copie.

La tâche revient donc à la copie. Il existe différentes façons de résoudre ce problème, mais dans ce cas, il est plus facile (et moins cher) de sélectionner la colonne en premier, puis de sélectionner des parties des colonnes à affecter.

Code de test:

df = pd.DataFrame(np.zeros((20, 3)), columns=['feature_a', 'b', 'c'])
df.feature_a.iloc[[1, 3, 15]] = 88
print(df)

Résultats:

    feature_a    b    c
0         0.0  0.0  0.0
1        88.0  0.0  0.0
2         0.0  0.0  0.0
3        88.0  0.0  0.0
4         0.0  0.0  0.0
5         0.0  0.0  0.0
6         0.0  0.0  0.0
7         0.0  0.0  0.0
8         0.0  0.0  0.0
9         0.0  0.0  0.0
10        0.0  0.0  0.0
11        0.0  0.0  0.0
12        0.0  0.0  0.0
13        0.0  0.0  0.0
14        0.0  0.0  0.0
15       88.0  0.0  0.0
16        0.0  0.0  0.0
17        0.0  0.0  0.0
18        0.0  0.0  0.0
19        0.0  0.0  0.0
Stephen Rauch
la source
1
Cela peut fonctionner, mais pourquoi?
Matthew Drury