Ajouter une colonne avec une valeur constante à pandas dataframe [duplicate]

99

Étant donné un DataFrame:

np.random.seed(0)
df = pd.DataFrame(np.random.randn(3, 3), columns=list('ABC'), index=[1, 2, 3])
df

          A         B         C
1  1.764052  0.400157  0.978738
2  2.240893  1.867558 -0.977278
3  0.950088 -0.151357 -0.103219

Quelle est la manière la plus simple d'ajouter une nouvelle colonne contenant une valeur constante, par exemple 0?

          A         B         C  new
1  1.764052  0.400157  0.978738    0
2  2.240893  1.867558 -0.977278    0
3  0.950088 -0.151357 -0.103219    0

C'est ma solution, mais je ne sais pas pourquoi cela met NaN dans la «nouvelle» colonne?

df['new'] = pd.Series([0 for x in range(len(df.index))])

          A         B         C  new
1  1.764052  0.400157  0.978738  0.0
2  2.240893  1.867558 -0.977278  0.0
3  0.950088 -0.151357 -0.103219  NaN
yemu
la source
9
si vous utilisez un index, ça va. df['new'] = pd.Series([0 for x in range(len(df.index))], index=df.index).
zach le
5
aussi, une compréhension de liste est totalement inutile ici. just do[0] * len(df.index)
acushner
@joris, je voulais dire que df ['new'] = 0 montre la bonne raison d'attribuer des zéros à toute la colonne, mais cela n'explique pas pourquoi ma première tentative insère NaN. Cela a été répondu par le Philip Cloud dans la réponse que j'ai acceptée.
yemu
6
Simplement fairedf['new'] = 0
flow2k

Réponses:

21

La raison pour laquelle cela met NaNdans une colonne est que df.indexet le Indexde votre objet de droite sont différents. @zach montre la bonne façon d'attribuer une nouvelle colonne de zéros. En général, pandasessaie de faire autant d'alignement d'indices que possible. Un inconvénient est que lorsque les indices ne sont pas alignés, vous obtenez NaNlà où ils ne sont pas alignés. Jouez avec les méthodes reindexet alignpour acquérir une certaine intuition pour l'alignement fonctionne avec des objets qui ont des indices partiellement, totalement et non alignés - tous alignés. Par exemple, voici comment DataFrame.align()fonctionne avec des indices partiellement alignés:

In [7]: from pandas import DataFrame

In [8]: from numpy.random import randint

In [9]: df = DataFrame({'a': randint(3, size=10)})

In [10]:

In [10]: df
Out[10]:
   a
0  0
1  2
2  0
3  1
4  0
5  0
6  0
7  0
8  0
9  0

In [11]: s = df.a[:5]

In [12]: dfa, sa = df.align(s, axis=0)

In [13]: dfa
Out[13]:
   a
0  0
1  2
2  0
3  1
4  0
5  0
6  0
7  0
8  0
9  0

In [14]: sa
Out[14]:
0     0
1     2
2     0
3     1
4     0
5   NaN
6   NaN
7   NaN
8   NaN
9   NaN
Name: a, dtype: float64
Phillip Cloud
la source
8
Je n'ai pas voté contre mais votre code manque de commentaires, il est difficile de suivre ce que vous essayez d'atteindre dans l'extrait de code
réparation le
8
Cela ne répond pas vraiment à la question. OP demande comment ajouter une nouvelle colonne contenant une valeur constante.
cs95
Je ne suis pas d'accord qu'il n'y ait qu'une seule question ici. Il y a "Comment attribuer une valeur constante à une colonne?" ainsi que "Ma tentative de faire cela ne fonctionne pas de manière X, pourquoi se comporte-t-elle de manière inattendue?" Je crois avoir abordé les deux points, le premier en faisant référence à une autre réponse. Veuillez lire tout le texte de ma réponse.
Phillip Cloud
Je pense que le problème vient de la question plutôt que de votre réponse. Il y a deux questions distinctes contenues dans ce post et, par conséquent, deux réponses distinctes sont nécessaires pour répondre à la question. Je pense que cela aurait dû être signalé comme étant trop large et l'affiche aurait dû poser deux questions distinctes.
Kevin
74

Affectation sur place très simple: df['new'] = 0

Pour une modification sur place, effectuez une affectation directe. Cette affectation est diffusée par des pandas pour chaque ligne.

df = pd.DataFrame('x', index=range(4), columns=list('ABC'))
df

   A  B  C
0  x  x  x
1  x  x  x
2  x  x  x
3  x  x  x

df['new'] = 'y'
# Same as,
# df.loc[:, 'new'] = 'y'
df

   A  B  C new
0  x  x  x   y
1  x  x  x   y
2  x  x  x   y
3  x  x  x   y

Remarque pour les colonnes d'objets

Si vous souhaitez ajouter une colonne de listes vides, voici mon conseil:

  • Envisagez de ne pas faire cela. objectles colonnes sont de mauvaises nouvelles en termes de performances. Repensez la structure de vos données.
  • Envisagez de stocker vos données dans une structure de données clairsemée. Pour plus d'informations: structures de données clairsemées
  • Si vous devez stocker une colonne de listes, veillez à ne pas copier plusieurs fois la même référence.

    # Wrong
    df['new'] = [[]] * len(df)
    # Right
    df['new'] = [[] for _ in range(len(df))]

Générer une copie: df.assign(new=0)

Si vous avez besoin d'une copie à la place, utilisez DataFrame.assign:

df.assign(new='y')

   A  B  C new
0  x  x  x   y
1  x  x  x   y
2  x  x  x   y
3  x  x  x   y

Et, si vous devez attribuer plusieurs de ces colonnes avec la même valeur, c'est aussi simple que,

c = ['new1', 'new2', ...]
df.assign(**dict.fromkeys(c, 'y'))

   A  B  C new1 new2
0  x  x  x    y    y
1  x  x  x    y    y
2  x  x  x    y    y
3  x  x  x    y    y

Affectation de plusieurs colonnes

Enfin, si vous devez affecter plusieurs colonnes avec des valeurs différentes, vous pouvez utiliser assignavec un dictionnaire.

c = {'new1': 'w', 'new2': 'y', 'new3': 'z'}
df.assign(**c)

   A  B  C new1 new2 new3
0  x  x  x    w    y    z
1  x  x  x    w    y    z
2  x  x  x    w    y    z
3  x  x  x    w    y    z
cs95
la source
13

Avec les pandas modernes, vous pouvez simplement faire:

df['new'] = 0
Roko Mijic
la source
1
Pouvez-vous indiquer quelles réponses spécifiques sont obsolètes? Laissons un commentaire en dessous pour que les auteurs aient une chance de s'améliorer.
cs95 le
Je pense que la réponse de Phillip Cloud est dépassée. La réponse par cs95 me semble correcte mais elle complique un peu les choses à l'OMI. Il s'agit d'un monoplace plus simple; du moins pour la question posée.
Roko Mijic le
1
Pour info, la seule différence entre cette réponse et la réponse cs95 (AKA, moi) est le nom et la valeur de la colonne. Toutes les pièces sont là.
cs95 le
7

Voici une autre doublure utilisant des lambdas (créez une colonne avec une valeur constante = 10)

df['newCol'] = df.apply(lambda x: 10, axis=1)

avant

df
    A           B           C
1   1.764052    0.400157    0.978738
2   2.240893    1.867558    -0.977278
3   0.950088    -0.151357   -0.103219

après

df
        A           B           C           newCol
    1   1.764052    0.400157    0.978738    10
    2   2.240893    1.867558    -0.977278   10
    3   0.950088    -0.151357   -0.103219   10
Grant Shannon
la source
4
df['newCol'] = 10est également une doublure (et est plus rapide). Quel est l'avantage d'utiliser apply here?
cs95
1
ne pas essayer de rivaliser avec vous ici - simplement montrer une approche alternative.
Grant Shannon
@ cs95 Ceci est utile. Je voulais créer une nouvelle colonne où chaque valeur était une liste vide distincte. Seule cette méthode fonctionne.
Yatharth Agarwal
@YatharthAgarwal Je vais vous donner cela, mais cela a également du sens étant donné que les pandas ne sont pas conçus pour fonctionner correctement avec des colonnes de listes.
cs95
1
@YatharthAgarwal Si vous avez besoin d'attribuer des listes vides, c'est toujours une solution médiocre car elle utilise apply. Essayezdf['new'] = [[] for _ in range(len(df))]
cs95 le