Python pandas inserta la lista en una celda

105

Tengo una lista 'abc' y un marco de datos 'df':

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

Quiero insertar la lista en la celda 1B, así que quiero este resultado:

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

¿Cómo puedo hacer eso?

1) Si uso esto:

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

Recibo el siguiente mensaje de error:

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

porque intenta insertar la lista (que tiene dos elementos) en una fila / columna pero no en una celda.

2) Si uso esto:

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

luego inserta una lista que tiene solo un elemento que es la lista 'abc' ( [['foo', 'bar']]).

3) Si uso esto:

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

luego inserta una cadena: ( foo, bar) pero no una lista.

4) Si uso esto:

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

luego inserta una lista pero solo tiene un elemento ( ['foo, bar']) pero no dos como quiero ( ['foo', 'bar']).

¡Gracias por la ayuda!


EDITAR

Mi nuevo marco de datos y la lista anterior:

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

Otro marco de datos:

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

Quiero insertar la lista 'abc' en df2.loc[1,'B']y / o df3.loc[1,'B'].

Si el marco de datos tiene columnas solo con valores enteros y / o valores NaN y / o valores de lista, entonces insertar una lista en una celda funciona perfectamente. Si el marco de datos tiene columnas solo con valores de cadena y / o valores NaN y / o valores de lista, entonces insertar una lista en una celda funciona perfectamente. Pero si el marco de datos tiene columnas con valores enteros y de cadena y otras columnas, aparece el mensaje de error si uso esto: df2.loc[1,'B'] = abco df3.loc[1,'B'] = abc.

Otro marco de datos:

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

Estos insertos funcionan perfectamente: df.loc[1,'B'] = abco df4.loc[1,'B'] = abc.

ragesz
fuente
1
¿Qué versión de pandas estás usando? lo siguiente funcionó usando pandas 0.15.0:df.loc[1,'b'] = ['foo','bar']
EdChum
¡Gracias! Utilizo Python 2.7 y probé pandas 0.14.0 y 0.15.0 y funcionó con los datos de prueba anteriores. Pero, ¿qué pasa si también tengo una columna 'C' con algunos valores enteros? 'A' tiene cadenas. Al tener una columna de entero y una columna de srting, obtengo el mismo error: ValueError: debe tener claves y valores de longitud iguales cuando se configura con un iterable
ragesz
Vas a tener que publicar datos y código para explicar y mostrar lo que quieres decir
EdChum

Respuestas:

119

Dado que set_valueha quedado obsoleto desde la versión 0.21.0, ahora debería usar at. Puede insertar una lista en una celda sin generar un " ValueErrorcomo loc". Creo que esto se debe a que at siempre se refiere a un valor único, mientras que locpuede referirse tanto a valores como a filas y columnas.

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

También debe asegurarse de que la columna en la que está insertando tenga dtype=object. Por ejemplo

>>> 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
fuente
4
Tuve que asegurarme de que el tipo de marco de datos original estuviera configurado para objetar para que esto funcionara:df = pd.DataFrame(data, dtype=object)
Takver
2
at necesita un índice. ¿Cómo me refiero a la fila usando otra coincidencia de valor de atributo? por ejemplo: para la fila con A = 2 en el ejemplo anterior?
bikashg
8
Esto devuelve otro error ValueError: setting an array element with a sequence.; vea una respuesta de @ cs95 si obtiene el error.
Blaszard
39

df3.set_value(1, 'B', abc)funciona para cualquier marco de datos. Tenga cuidado con el tipo de datos de la columna 'B'. P.ej. una lista no se puede insertar en una columna flotante, en ese caso df['B'] = df['B'].astype(object)puede ayudar.

ragesz
fuente
6
Tenga en cuenta que este comando ha quedado obsoleto . Hay una actualización justo debajo.
Thomas
35

Pandas> = 0,21

set_valueha quedado obsoleto. Ahora puede usar DataFrame.atpara establecer por etiqueta y DataFrame.iatpara establecer por posición entera.

Establecer valores de celda 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

Si desea establecer un valor en la segunda fila de la "B" para alguna lista nueva, use DataFrane.at:

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

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

También puede establecer por posición entera usando DataFrame.iat

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

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

¿Y si consigo ValueError: setting an array element with a sequence?

Intentaré reproducir esto 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.

Esto se debe a que su objeto es de tipo float64d, mientras que las listas son objects, por lo que hay una falta de coincidencia allí. Lo que tendría que hacer en esta situación es convertir la columna en objeto primero.

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

A     int64
B    object
dtype: object

Entonces, funciona:

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

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

Posible, pero hacky

Aún más loco, descubrí que puedes piratear DataFrame.locpara lograr algo similar si pasas listas anidadas.

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

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

Puede leer más sobre por qué esto funciona aquí.

cs95
fuente
2

Trabajo rápido

Simplemente incluya la lista dentro de una nueva lista, como se hizo para col2 en el marco de datos a continuación. La razón por la que funciona es que Python toma la lista externa (de listas) y la convierte en una columna como si contuviera elementos escalares normales, que son listas en nuestro caso y no escalares normales.

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

También obteniendo

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

usar .at en lugar de .loc no hizo ninguna diferencia en mi caso, pero hacer cumplir el tipo de datos de la columna del marco de datos hizo el truco:

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

Luego, podría establecer listas, matrices numpy y todo tipo de cosas como valores de celda única en mis marcos de datos.

Maxime Beau
fuente