I panda Python inseriscono l'elenco in una cella


105

Ho un elenco "abc" e un dataframe "df":

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

Voglio inserire l'elenco nella cella 1B, quindi voglio questo risultato:

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

Come posso farlo?

1) Se uso questo:

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

Ricevo il seguente messaggio di errore:

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

perché cerca di inserire l'elenco (che ha due elementi) in una riga / colonna ma non in una cella.

2) Se uso questo:

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

quindi inserisce una lista che ha un solo elemento che è la lista 'abc' ( [['foo', 'bar']]).

3) Se uso questo:

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

quindi inserisce una stringa: ( foo, bar) ma non una lista.

4) Se uso questo:

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

quindi inserisce una lista ma ha solo un elemento ( ['foo, bar']) ma non due come voglio ( ['foo', 'bar']).

Grazie per l'aiuto!


MODIFICARE

Il mio nuovo dataframe e il vecchio elenco:

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

Un altro dataframe:

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

Voglio inserire l'elenco "abc" in df2.loc[1,'B']e / o df3.loc[1,'B'].

Se il dataframe ha colonne solo con valori interi e / o valori NaN e / o valori di elenco, l'inserimento di un elenco in una cella funziona perfettamente. Se il dataframe ha colonne solo con valori stringa e / o valori NaN e / o valori elenco, l'inserimento di un elenco in una cella funziona perfettamente. Ma se il dataframe ha colonne con valori interi e stringa e altre colonne, viene visualizzato il messaggio di errore se uso questo: df2.loc[1,'B'] = abco df3.loc[1,'B'] = abc.

Un altro dataframe:

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

Questi inserti funzionano perfettamente: df.loc[1,'B'] = abco df4.loc[1,'B'] = abc.


1
Quale versione di Panda stai usando? i seguenti hanno lavorato usando i panda 0.15.0:df.loc[1,'b'] = ['foo','bar']
EdChum

Grazie! Uso Python 2.7 e ho provato i panda 0.14.0 e 0.15.0 e ha funzionato con i dati di test sopra. Ma cosa succede se ho anche una colonna "C" con alcuni valori interi? "A" ha stringhe. Avendo una colonna intera e una colonna srting ottengo lo stesso errore: ValueError: deve avere chiavi e valore len uguali quando si imposta con un iterabile
ragesz

Dovrai pubblicare dati e codice per spiegare e mostrare cosa intendi
EdChum

Risposte:


119

Poiché set_valueè stato deprecato dalla versione 0.21.0, ora dovresti usare at. Può inserire un elenco in una cella senza sollevare un ValueErroras locdo. Penso che ciò sia dovuto al fatto che at si riferisce sempre a un singolo valore, mentre locpuò fare riferimento a valori oltre a righe e colonne.

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

Devi anche assicurarti che la colonna in cui stai inserendo abbia dtype=object. Per esempio

>>> 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

4
Ho dovuto assicurarmi che il dtype del dataframe originale fosse impostato su object affinché funzionasse:df = pd.DataFrame(data, dtype=object)
Takver

2
at ha bisogno di un indice. Come faccio a fare riferimento alla riga utilizzando un'altra corrispondenza del valore dell'attributo; es: per la riga con A = 2 nell'esempio sopra?
bikashg

8
Ciò restituisce un altro errore ValueError: setting an array element with a sequence.; vedi una risposta da @ cs95 se ottieni l'errore.
Blaszard

39

df3.set_value(1, 'B', abc)funziona per qualsiasi dataframe. Prenditi cura del tipo di dati della colonna "B". Per esempio. una lista non può essere inserita in una colonna float, in quel caso df['B'] = df['B'].astype(object)può aiutare.


6
Nota che questo comando è stato deprecato . C'è un aggiornamento proprio sotto.
Thomas

35

Panda> = 0,21

set_valueè stato deprecato. È ora possibile utilizzare DataFrame.atper impostare per etichetta e DataFrame.iatper impostare per posizione intera.

Impostazione dei valori delle celle con 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

Se desideri impostare un valore nella seconda riga della "B" su un nuovo elenco, utilizza DataFrane.at:

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

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

Puoi anche impostare per posizione intera usando DataFrame.iat

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

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

E se ottengo ValueError: setting an array element with a sequence?

Proverò a riprodurlo con:

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.

Ciò è dovuto al fatto che il tuo oggetto è di tipo float64d, mentre le liste sono objects, quindi c'è una mancata corrispondenza lì. Quello che dovresti fare in questa situazione è convertire prima la colonna in oggetto.

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

A     int64
B    object
dtype: object

Quindi, funziona:

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

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

Possibile, ma Hacky

Ancora più stravagante, ho scoperto che puoi hackerare DataFrame.locper ottenere qualcosa di simile se passi elenchi annidati.

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

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

Puoi leggere di più sul motivo per cui funziona qui.



2

Rapido lavoro intorno

Racchiudi semplicemente l'elenco all'interno di un nuovo elenco, come fatto per col2 nel frame di dati sottostante. Il motivo per cui funziona è che python prende la lista esterna (di liste) e la converte in una colonna come se contenesse normali elementi scalari, che nel nostro caso sono liste e non normali scalari.

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]

0

Anche ottenendo

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

l'utilizzo di .at anziché .loc non ha fatto alcuna differenza nel mio caso, ma l'applicazione del tipo di dati della colonna dataframe ha fatto il trucco:

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

Quindi potrei impostare elenchi, array numpy e ogni sorta di cose come valori di cella singola nei miei dataframe.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.