Si vous essayez d'ajouter une série à une trame de données pandas, elle se comporte comme une jointure, alors soyez prudent.
Lors du traitement de données avec des pandas, le processus d'ajout de colonnes à une trame de données est fréquent. Il existe deux méthodes principales pour ajouter des colonnes à un dayframe.
pd.DataFrame.assign
** 1. Ajoutez une colonne en spécifiant le nom de la colonne **
df['new_col'] = data
** 2. Ajouter une colonne à l'aide de la méthode assign **
df.assign(new_col=data)
Dans les deux cas, vous pouvez transmettre une liste de valeurs égales, de tailles, np.array
, pd.Series
, etc.
Préparez une série avec le même nombre d'enregistrements que n'importe quelle trame de données.
df = pd.DataFrame(
[[1,2,3], [4,5,6], [7,8,9]],
columns=['a', 'b', 'c'],
index=[1,2,3]
)
sr = pd.Series([-1, -2, -3])
df
# a b c
# 1 1 2 3
# 2 4 5 6
# 3 7 8 9
sr
# 0 -1
# 1 -2
# 2 -3
# dtype: int64
Si vous voulez ajouter les données de sr
en tant que nouvelle colonne'd'
à df
, procédez comme suit.
df = df.assign(d=sr)
J'espère qu'une telle table sera créée.
a | b | c | d | |
---|---|---|---|---|
1 | 1 | 2 | 3 | -1 |
2 | 4 | 5 | 6 | -2 |
3 | 7 | 8 | 9 | -3 |
Cependant, en réalité, une telle trame de données est renvoyée.
a | b | c | d | |
---|---|---|---|---|
1 | 1 | 2 | 3 | -2 |
2 | 4 | 5 | 6 | -3 |
3 | 7 | 8 | 9 | NaN |
Lorsque vous comparez à nouveau le bloc de données et la série, les index des deux ne correspondent pas. Avec de telles données, vous pouvez voir que même dans le cas d'une affectation, cela se comporte comme une jointure.
Cela peut être évité en le passant comme np.array.
df.assign(new_col=new_series.values)
Remarque: En ce qui concerne le Document officiel, la méthode to_numpy
est utilisée plutôt que la méthode values
. Il est recommandé de le faire.
Cela ressemble à ceci pour distinguer clairement l''Extension Arary 'ajoutée dans 0.24 des pandas.
Tout d'abord, la méthode pd.DataFrame.assign
est uniquement appelée en interne pour le processus 1 affiché au début si la valeur passée n'est pas appelable. Par conséquent, un phénomène comme celui-ci se produit dans les deux méthodes.
(Au fait, "la valeur passée est appelable" correspond au cas de l'appel de la colonne du bloc de données lui-même avec une expression lambda
etc.) [^ callable]
Si vous essayez d'affecter quelque chose comme df ['X'] = hogehoge
,pd.DataFrame .__ setitem__ ()
sera appelé. En suivant le code, j'ai trouvé la docstring suivante. [^ setitem]
"""
Add series to DataFrame in specified column.
If series is a numpy-array (not a Series/TimeSeries), it must be the
same length as the DataFrames index or an error will be thrown.
Series/TimeSeries will be conformed to the DataFrames index to
ensure homogeneity.
"""
En d'autres termes, les données transmises sont
Il est indiqué qu'il sera traité de cette manière. Si vous suivez le code plus loin, vous pouvez voir que les données sont triées selon l'index du bloc de données avant d'être ajoutées. [^ réindexer]
Ce phénomène a été causé en pensant à la série de la même manière qu'un tableau. Comme vous pouvez le voir ci-dessous, nous avons également constaté que la taille de la série ne devait même pas correspondre à l'enregistrement dans le bloc de données à ajouter, elle était complètement différente de la liste ou du tableau.
df.assign(
x=pd.Series([3], index=[2])
)
# a b c x
# 1 1 2 3 NaN
# 2 4 5 6 3.0
# 3 7 8 9 NaN
N'ajoutez pas de données unidimensionnelles de même taille à un bloc de données comme une liste ou un tableau. Lors de l'affectation d'une série à une colonne d'une trame de données, le processus se déroule sans erreur même si la taille est différente, il semble donc que le risque de créer un bogue sans s'en apercevoir augmente. J'ai toujours averti que je le convertirais en numpy-array et effectuerais le processus d'attribution.
Recommended Posts