Python-Pandas fügen eine Liste in eine Zelle ein

104

Ich habe eine Liste 'abc' und einen Datenrahmen 'df':

abc = ['foo', 'bar']
df =
    A  B
0  12  NaN
1  23  NaN

Ich möchte die Liste in Zelle 1B einfügen, also möchte ich dieses Ergebnis:

    A  B
0  12  NaN
1  23  ['foo', 'bar']

Wie kann ich das machen?

1) Wenn ich das benutze:

df.ix[1,'B'] = abc

Ich erhalte die folgende Fehlermeldung:

ValueError: Must have equal len keys and value when setting with an iterable

weil es versucht, die Liste (die zwei Elemente enthält) in eine Zeile / Spalte, aber nicht in eine Zelle einzufügen.

2) Wenn ich das benutze:

df.ix[1,'B'] = [abc]

dann wird eine Liste eingefügt, die nur ein Element enthält, nämlich die 'abc'-Liste ( [['foo', 'bar']]).

3) Wenn ich das benutze:

df.ix[1,'B'] = ', '.join(abc)

dann fügt es eine Zeichenfolge ein: ( foo, bar), aber keine Liste.

4) Wenn ich das benutze:

df.ix[1,'B'] = [', '.join(abc)]

dann fügt es eine Liste ein, aber es hat nur ein Element ( ['foo, bar']), aber nicht zwei, wie ich will ( ['foo', 'bar']).

Danke für die Hilfe!


BEARBEITEN

Mein neuer Datenrahmen und die alte Liste:

abc = ['foo', 'bar']
df2 =
    A    B         C
0  12  NaN      'bla'
1  23  NaN  'bla bla'

Ein weiterer Datenrahmen:

df3 =
    A    B         C                    D
0  12  NaN      'bla'  ['item1', 'item2']
1  23  NaN  'bla bla'        [11, 12, 13]

Ich möchte die 'abc'-Liste in df2.loc[1,'B']und / oder einfügen df3.loc[1,'B'].

Wenn der Datenrahmen nur Spalten mit ganzzahligen Werten und / oder NaN-Werten und / oder Listenwerten enthält, funktioniert das Einfügen einer Liste in eine Zelle einwandfrei. Wenn der Datenrahmen nur Spalten mit Zeichenfolgenwerten und / oder NaN-Werten und / oder Listenwerten enthält, funktioniert das Einfügen einer Liste in eine Zelle einwandfrei. Wenn der Datenrahmen jedoch Spalten mit Ganzzahl- und Zeichenfolgenwerten sowie andere Spalten enthält, wird die Fehlermeldung angezeigt, wenn ich Folgendes verwende:df2.loc[1,'B'] = abc oder df3.loc[1,'B'] = abc.

Ein weiterer Datenrahmen:

df4 =
          A     B
0      'bla'  NaN
1  'bla bla'  NaN

Diese Einsätze funktionieren perfekt: df.loc[1,'B'] = abcoder df4.loc[1,'B'] = abc.

ragesz
quelle
1
Welche Version Pandas verwenden Sie? Folgendes funktionierte mit Pandas 0.15.0:df.loc[1,'b'] = ['foo','bar']
EdChum
Danke dir! Ich benutze Python 2.7 und habe Pandas 0.14.0 und 0.15.0 ausprobiert und es hat mit den obigen Testdaten funktioniert. Aber was ist, wenn ich auch eine 'C'-Spalte mit einigen ganzzahligen Werten habe? 'A' hat Zeichenfolgen. Mit einer Integer-Spalte und einer Srting-Spalte erhalte ich den gleichen Fehler: ValueError: Muss gleiche Len-Schlüssel und Wert haben, wenn mit einem iterable
ragesz
Sie müssen Daten und Code posten, um zu erklären und zu zeigen, was Sie meinen
EdChum

Antworten:

118

Da set_valueist veraltet seit Version 0.21.0, sollten Sie jetzt verwenden at. Es kann eine Liste in eine Zelle einfügen, ohne ein ValueErroras zu erhöhen loc. Ich denke, das liegt daran, dass es sich at immer auf einen einzelnen Wert bezieht, während loces sich sowohl auf Werte als auch auf Zeilen und Spalten beziehen kann.

df = pd.DataFrame(data={'A': [1, 2, 3], 'B': ['x', 'y', 'z']})

df.at[1, 'B'] = ['m', 'n']

df =
    A   B
0   1   x
1   2   [m, n]
2   3   z

Sie müssen auch sicherstellen, dass die Spalte, in die Sie einfügen, vorhanden ist dtype=object. Beispielsweise

>>> df = pd.DataFrame(data={'A': [1, 2, 3], 'B': [1,2,3]})
>>> df.dtypes
A    int64
B    int64
dtype: object

>>> df.at[1, 'B'] = [1, 2, 3]
ValueError: setting an array element with a sequence

>>> df['B'] = df['B'].astype('object')
>>> df.at[1, 'B'] = [1, 2, 3]
>>> df
   A          B
0  1          1
1  2  [1, 2, 3]
2  3          3
Michael Hays
quelle
3
Ich musste sicherstellen, dass der ursprüngliche Datenrahmen-D-Typ so eingestellt war, dass er Einwände erhebt, damit dies funktioniert:df = pd.DataFrame(data, dtype=object)
Takver
2
at braucht einen Index. Wie verweise ich auf die Zeile mit einer anderen Attributwertübereinstimmung? zB: für die Zeile mit A = 2 im obigen Beispiel?
Bikashg
8
Dies gibt einen weiteren Fehler zurück ValueError: setting an array element with a sequence.. Sehen Sie eine Antwort von @ cs95, wenn Sie den Fehler erhalten.
Blaszard
39

df3.set_value(1, 'B', abc)funktioniert für jeden Datenrahmen. Achten Sie auf den Datentyp der Spalte 'B'. Z.B. Eine Liste kann nicht in eine Float-Spalte eingefügt werden. In diesem Fall df['B'] = df['B'].astype(object)kann dies hilfreich sein.

ragesz
quelle
6
Beachten Sie, dass dieser Befehl veraltet ist . Es gibt ein Update direkt unten.
Thomas
35

Pandas> = 0,21

set_valuewurde veraltet. Sie können jetzt verwenden DataFrame.at, um nach Beschriftung und DataFrame.iatnach ganzzahliger Position festzulegen.

Einstellen der Zellenwerte mit at/iat

# Setup
df = pd.DataFrame({'A': [12, 23], 'B': [['a', 'b'], ['c', 'd']]})
df

    A       B
0  12  [a, b]
1  23  [c, d]

df.dtypes

A     int64
B    object
dtype: object

Wenn Sie einen Wert in der zweiten Zeile des "B" für eine neue Liste festlegen möchten, verwenden Sie DataFrane.at:

df.at[1, 'B'] = ['m', 'n']
df

    A       B
0  12  [a, b]
1  23  [m, n]

Sie können auch die Ganzzahlposition mit festlegen DataFrame.iat

df.iat[1, df.columns.get_loc('B')] = ['m', 'n']
df

    A       B
0  12  [a, b]
1  23  [m, n]

Was ist, wenn ich bekomme ValueError: setting an array element with a sequence?

Ich werde versuchen, dies zu reproduzieren mit:

df

    A   B
0  12 NaN
1  23 NaN

df.dtypes

A      int64
B    float64
dtype: object

df.at[1, 'B'] = ['m', 'n']
# ValueError: setting an array element with a sequence.

Dies liegt daran, dass Ihr Objekt vom float64Typ dtype ist, während Listen objects sind, sodass dort eine Nichtübereinstimmung vorliegt . In dieser Situation müssten Sie zuerst die Spalte in ein Objekt konvertieren.

df['B'] = df['B'].astype(object)
df.dtypes

A     int64
B    object
dtype: object

Dann funktioniert es:

df.at[1, 'B'] = ['m', 'n']
df

    A       B
0  12     NaN
1  23  [m, n]

Möglich, aber Hacky

Noch verrückter, ich habe festgestellt, dass Sie sich durchhacken können DataFrame.loc, um etwas Ähnliches zu erreichen, wenn Sie verschachtelte Listen übergeben.

df.loc[1, 'B'] = [['m'], ['n'], ['o'], ['p']]
df

    A             B
0  12        [a, b]
1  23  [m, n, o, p]

Lesen Sie hier mehr darüber, warum dies funktioniert .

cs95
quelle
2

Schnelle Abhilfe

Fügen Sie die Liste einfach in eine neue Liste ein, wie für col2 im Datenrahmen unten. Der Grund dafür ist, dass Python die äußere Liste (von Listen) nimmt und sie in eine Spalte konvertiert, als ob sie normale Skalarelemente enthalten würde, in unserem Fall Listen und keine normalen Skalare.

mydict={'col1':[1,2,3],'col2':[[1, 4], [2, 5], [3, 6]]}
data=pd.DataFrame(mydict)
data


   col1     col2
0   1       [1, 4]
1   2       [2, 5]
2   3       [3, 6]
Pallavi Jindal
quelle
0

Auch bekommen

ValueError: Must have equal len keys and value when setting with an iterable,

Die Verwendung von .at anstelle von .loc hat in meinem Fall keinen Unterschied gemacht, aber das Erzwingen des Datentyps der Datenrahmenspalte hat den Trick getan:

df['B'] = df['B'].astype(object)

Dann könnte ich Listen, Numpy-Arrays und alles Mögliche als Einzelzellenwerte in meinen Datenrahmen festlegen.

Maxime Beau
quelle