Ajouter une colonne dans le cadre de données à partir de la liste

95

J'ai un dataframe avec quelques colonnes comme ceci:

A   B   C  
0   
4
5
6
7
7
6
5

La plage de valeurs possible dans A est uniquement de 0 à 7 .

De plus, j'ai une liste de 8 éléments comme celui-ci:

List=[2,5,6,8,12,16,26,32]  //There are only 8 elements in this list

Si l'élément de la colonne A est n , je dois insérer le n ème élément de la liste dans une nouvelle colonne, dites «D».

Comment puis-je faire cela en une seule fois sans boucler sur toute la trame de données?

Le dataframe résultant ressemblerait à ceci:

A   B   C   D
0           2
4           12
5           16
6           26
7           32
7           32
6           26
5           16

Remarque: le dataframe est énorme et l'itération est la dernière option. Mais je peux aussi organiser les éléments dans 'List' dans n'importe quelle autre structure de données comme dict si nécessaire.

crinière
la source
1
Je pense que vous avez besoin d'un exemple de jouet (plus petit), avec le résultat souhaité. Cela semble un peu vague atm.
Andy Hayden
11
N'appelez jamais une variable "Liste". Dans n'importe quelle langue.
lucid_dreamer

Réponses:

51

IIUC, si vous transformez votre (malheureusement nommé) Listen un ndarray, vous pouvez simplement l'indexer naturellement.

>>> import numpy as np
>>> m = np.arange(16)*10
>>> m[df.A]
array([  0,  40,  50,  60, 150, 150, 140, 130])
>>> df["D"] = m[df.A]
>>> df
    A   B   C    D
0   0 NaN NaN    0
1   4 NaN NaN   40
2   5 NaN NaN   50
3   6 NaN NaN   60
4  15 NaN NaN  150
5  15 NaN NaN  150
6  14 NaN NaN  140
7  13 NaN NaN  130

Ici, j'ai construit un nouveau m, mais si vous utilisez m = np.asarray(List), la même chose devrait fonctionner: les valeurs dans df.Asélectionneront les éléments appropriés de m.


Notez que si vous utilisez une ancienne version de numpy, vous devrez peut-être utiliser à la m[df.A.values]place - dans le passé, numpyne jouait pas bien avec les autres, et certaines refactorisations ont pandascausé des maux de tête. Les choses se sont améliorées maintenant.

DSM
la source
Salut @DSM. Je comprends ce que vous dites mais j'obtiens cette erreur: Traceback (most recent call last): File "./b.py", line 24, in <module> d["D"] = m[d.A] IndexError: unsupported iterator index
crinière
1
@mane: urf, c'est un vieux numpybug. Ça d["D"] = m[d.A.values]marche pour toi?
DSM
277

Attribuez simplement la liste directement:

df['new_col'] = mylist

Alternative
Convertissez la liste en série ou en tableau, puis attribuez:

se = pd.Series(mylist)
df['new_col'] = se.values

ou

df['new_col'] = np.array(mylist)
moineau
la source
3
pykernel_launcher.py:1: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy """Entry point for launching an IPython kernel.
Ilya Rusin
@sparrow utilisera l' pd.Serieseffet dtype? Je veux dire, laissera-t-il des flotteurs en tant que flotteurs et des chaînes en tant que chaînes? Ou les éléments de la liste seront-ils par défaut des chaînes?
3kstc
2
@IlyaRusin, c'est un faux positif qui peut être ignoré dans ce cas. Pour plus d'informations: stackoverflow.com/questions/20625582/…
sparrow
1
Cela peut être simplifié à: df ['new_col'] = pd.Series (mylist) .values
smartse
15

Une solution améliorant la grande de @sparrow.

Soit df , votre jeu de données et mylist la liste avec les valeurs que vous souhaitez ajouter au dataframe.

Supposons que vous souhaitiez appeler simplement votre nouvelle colonne, new_column

Commencez par transformer la liste en une série:

column_values = pd.Series(mylist)

Utilisez ensuite la fonction d' insertion pour ajouter la colonne. Cette fonction a l'avantage de vous permettre de choisir dans quelle position vous souhaitez placer la colonne. Dans l'exemple suivant, nous positionnerons la nouvelle colonne dans la première position à partir de la gauche (en définissant loc = 0)

df.insert(loc=0, column='new_column', value=column_values)
Salvatore Cosentino
la source
Cela ne fonctionnera pas si vous avez changé vos index de df en quelque chose d'autre que 1,2,3 ... dans ce cas, vous devez ajouter entre les lignes: column_values.index = df.index
Guy s
8

Commençons par créer le dataframe que vous aviez, j'ignorerai les colonnes B et C car elles ne sont pas pertinentes.

df = pd.DataFrame({'A': [0, 4, 5, 6, 7, 7, 6,5]})

Et la cartographie que vous désirez:

mapping = dict(enumerate([2,5,6,8,12,16,26,32]))

df['D'] = df['A'].map(mapping)

Terminé!

print df

Production:

   A   D
0  0   2
1  4  12
2  5  16
3  6  26
4  7  32
5  7  32
6  6  26
7  5  16
Phil Cooper
la source
1
Je pense que l'OP sait déjà comment faire cela. D'après ma lecture, le problème est de construire à Dpartir des éléments de Aet List("Si l'élément de la colonne A est n, je dois insérer le n ème élément de la liste dans une nouvelle colonne, dites" D ".")
DSM
SO s'est transformé en une sorte de F (* & nanny state. Merci à @DSM pour le commentaire, mais je n'ai pas pu corriger le message jusqu'à ce qu'il soit examiné par les pairs. Et puis il a été rejeté parce que c'était trop rapide. Et puis j'ai été capable de revoir ma propre modification par les pairs. Et puis il est trop tard car une pire réponse (à mon humble avis) a été "acceptée". Donc, il y a vraiment des méta-nounous qui sont moins qu'utiles !!!!
Phil Cooper
Eh bien, je ne peux pas parler pour les nounous, mais vous constaterez que votre approche est d'un ordre de grandeur plus lente sur de longs tableaux. À d'autres égards, bien sûr, choisir entre np.array(List)[df.A]et df["A"].map(dict(enumerate(List)))est surtout une question de préférence.
DSM
Salut Phil, je n'ai vu que votre solution et le commentaire de DSM et je n'y suis jamais revenu car la solution de DSM a bien fonctionné pour moi. Mais maintenant, en regardant votre solution, cela fonctionne aussi. J'ai exécuté la solution de DSM sur mon ensemble de données d'environ 200k entrées et elle s'exécute en quelques secondes avec tous les autres calculs que j'ai. Je suis totalement nouveau sur les python-pandas et personnellement je ne cherchais rien d'élégant ou de grand; tout ce qui fonctionnait était bien. Mais honnêtement, merci pour la solution.
crinière du
2

Ancienne question; mais j'essaye toujours d'utiliser le code le plus rapide!

J'avais une liste énorme avec 69 millions de uint64. np.array () a été le plus rapide pour moi.

df['hashes'] = hashes
Time spent: 17.034842014312744

df['hashes'] = pd.Series(hashes).values
Time spent: 17.141014337539673

df['key'] = np.array(hashes)
Time spent: 10.724546194076538
Mehdi
la source