J'ai une trame de données
a b 0 1 (0, 0, 1) 1 1 (0, 0, 1) 2 2 (1, 1, 0) 3 1 (0, 0, 1)
(créé par d = pd.DataFrame({'a':[1,1,2,1], 'b':[(1,1,0)]*4}) ).
Je voudrais attribuer des valeurs de tuple aux entrées indexées par des valeurs booléennes, par exemple
a b 0 1 ((0, 0, 1),) 1 1 ((0, 0, 1),) 2 2 (1, 1, 0) 3 1 ((0, 0, 1),)
pour changer les valeurs des lignes 0,1,3 en (0,0,1) . Cela ne fonctionne pas et lève une ValueError: Must have equal len keys and value when setting with an ndarray . Notez que d.loc[d['a']==1, 'b'] = [((0,0,1),)]*3 ne renvoie pas d'erreur, mais le résultat est
d.loc[d['a']==1, 'b'] = [(0,0,1)] * 3
Comment obtenir le résultat
a b 0 1 (1, 1, 0) 1 1 (1, 1, 0) 2 2 (1, 1, 0) 3 1 (1, 1, 0)
utiliser l'indexation logique pour les lignes?
4 Réponses :
Une façon de faire est de créer une série. Cependant, les indices doivent correspondre:
d.loc[d['a']==1, 'b'] = pd.Series([(0,0,1)]*len(d.loc[d['a']==1, 'b']), index=d.loc[d['a']==1, 'b'].index)
Cela semble un peu fastidieux et j'espère que quelqu'un d'autre publiera une meilleure solution.
(En utilisant le naïf d.loc[d['a']==1, 'b'] = pd.Series([(0,0,1)]*len(d.loc[d['a']==1, 'b'])) produit NaN dans la dernière ligne, car l'index 3 de la trame de données n'est pas satisfait par un index correspondant dans la série. Ceci: d.loc[d['a']==1, 'b'] = pd.Series([(0,0,1)]*len(d)) semble également fonctionner, mais semble terriblement inefficace surtout lorsque la plupart des conditions sont fausses.)
Voici une façon de faire:
d.loc[ixs, 'b'] = pd.Series(vals, index=ixs)
Pour les pandas> = 1.0, vous pouvez faire:
# set values ixs = [0,1,3] vals = [[(0,0,1)]*len(ixs)] # replace values d.loc[ixs,['b']] = vals a b 0 1 (0, 0, 1) 1 1 (0, 0, 1) 2 2 (1, 1, 0) 3 1 (0, 0, 1)
à votre santé. que la permutation des crochets ne m'était pas venue à l'esprit ...
Malheureusement, cette approche rompt avec Pandas 1.1.0
@zeeMonkeez J'ai mis à jour la solution avec une nouvelle approche.
Enveloppez simplement le tuple dans la liste
d.loc[d['a']==1, 'b'] = [[(0, 0, 1)]] Out[78]: a b 0 1 (0, 0, 1) 1 1 (0, 0, 1) 2 2 (1, 1, 0) 3 1 (0, 0, 1)
OK, c'est encore mieux. Quelle est la raison pour laquelle les doubles listes sont nécessaires?
Malheureusement, cette approche rompt avec Pandas 1.1.0
@zeeMonkeez: pandas 1.1.0+ ne permet pas d'attribuer avec une longueur incompatible comme dans ce cas. Une recarray de contournement consiste à attribuer à l'aide de recarray de numpy.
Pourquoi utiliser des tuples au lieu de colonnes?
Dans ce cas, ce sont des valeurs RVB, qui peuvent également être des valeurs RVBA. Il semble plus naturel de stocker dans une cellule que de le rassembler dynamiquement à partir de plusieurs colonnes, en tenant compte des valeurs A potentiellement manquantes.