He creado un Pandas DataFrame

df = DataFrame(index=['A','B','C'], columns=['x','y'])

y me esta

 x y 
Una NaN NaN 
B NaN NaN 
C NaN NaN 


Entonces quiero asignar un valor a la célula en particular, por ejemplo para la fila » C » y la columna ‘x’.
He esperado a obtener dicho resultado:

 x y 
Una NaN NaN 
B NaN NaN 
C 10 NaN 

con este código:

df.xs('C')['x'] = 10

pero el contenido de df no han cambiado. Es de nuevo sólo NaNs en DataFrame.

Alguna sugerencia?

  • No uso ‘encadenados indexación’ (df['x']['C']), el uso de df.ix['x','C'].
  • El orden de índice de acceso debe ser: dataframe[column (series)] [row (Series index)], mientras que muchas personas (incluyéndome a mí) son los más utilizados para la dataframe[row][column] orden. Como Matlab y R programador éste se siente más intuitiva para mí, pero que, aparentemente, no es la forma en que los Pandas funciona..
  • he intentado eso, pero terminé de agregar otra fila los nombres de x y otro de los nombres de columna C. usted tiene que hacer la primer fila, la columna. así df.ix[‘C’,’x’]=10
  • A @Yariv del comentario. Advertencia: a Partir de 0.20.0, el .ix indizador está en desuso, en favor de la más estricta .iloc y .loc indizadores. pandas.pydata.org/pandas-docs/stable/generated/… . df.al parece es que se pegue la vuelta.
InformationsquelleAutor Mitkp | 2012-12-12

18 Comentarios

  1. 458

    RukTech la respuesta, df.set_value('C', 'x', 10), es, de lejos, más rápido que las opciones que te he sugerido a continuación. Sin embargo, ha sido programado para desuso.

    Adelante, el método recomendado es .iat/.en.


    Por qué df.xs('C')['x']=10 no funciona:

    df.xs('C') por defecto, devuelve un nuevo dataframe con una copia de los datos, por lo

    df.xs('C')['x']=10

    modifica esta nueva dataframe sólo.

    df['x'] devuelve una vista de la df dataframe, así

    df['x']['C'] = 10

    modifica df sí mismo.

    Advertencia: a veces es difícil predecir si una operación devuelve una copia o una vista. Por esta razón, la docs recomiendan evitar las asignaciones con «encadenados indexación».


    Por lo que la alternativa recomendada es

    df.at['C', 'x'] = 10

    que hace modificar df.


    In [18]: %timeit df.set_value('C', 'x', 10)
    100000 loops, best of 3: 2.9 µs per loop
    
    In [20]: %timeit df['x']['C'] = 10
    100000 loops, best of 3: 6.31 µs per loop
    
    In [81]: %timeit df.at['C', 'x'] = 10
    100000 loops, best of 3: 9.2 µs per loop
    • No hay tal cosa como df.x en el API. ¿Qué quiere decir?
    • es el nombre de una columna en df. df.x devuelve un Series con los valores en la columna x. Voy a cambiar a df['x'] desde esta notación funcionará con cualquier nombre de columna (a diferencia de la notación de punto) y creo que es más claro.
    • Yo sabía que, pensé que ustedes estaban diciendo df.x era un desconocido nuevo método junto df.xs, df.ix
    • df.xs(..., copy=True) devuelve una copia, y que es el comportamiento predeterminado. df.xs(..., copy=False) devuelve el original.
    • De acuerdo a los mantenedores, esta no es la forma recomendada para establecer un valor. Consulte stackoverflow.com/a/21287235/1579844 y mi respuesta.
    • A veces, el encadenamiento es doloroso si usted tiene un gran índice de columna como datetime. No se puede escribir cada vez.
    • En mi caso, yo tenía una mezcla, es decir, de la ubicación del índice y la etiqueta de la columna. Me encontré con esta manera de hacerlo funcionar : df_temp.iat[0, df_temp.columns.get_loc('Cash')] = df_temp['Cash'].iloc[0] + start_val

  2. 209

    Actualización: El .set_value método va a ser obsoleto. .iat/.at son buenos reemplazos, por desgracia pandas proporciona poca documentación


    La manera más rápida de hacer esto es usando la set_value. Este método es de ~100 veces más rápido que .ix método. Por ejemplo:

    df.set_value('C', 'x', 10)

    • Es incluso mejor que df['x']['C'] = 10 .
    • 1000 vueltas, la mejor de las 3: 195 µs por bucle «df[‘x’][‘C’] = 10» 1000 vueltas, la mejor de las 3: 310 µs por bucle «en el df.ix[‘C’,’x’] = 10» 1000 vueltas, la mejor de las 3: 189 µs por bucle «en el df.xs(‘C’, copie=False) [«x»] = 10″ 1000 vueltas, la mejor de las 3: 7.22 µs por bucle «en el df.set_value(‘C’, ‘x’, 10)»
    • ¿esto también funciona para agregar una nueva fila/col para el dataframe?
    • Sí lo hace (para pandas 0.16.2)
    • Es posible el uso de este para establecer un valor a una df=df.append(df.sum(numeric_only=True),ignore_index=True) ?
    • Esta es obsoleto
    • realmente es el fastest en el momento.
    • Como para el día de hoy, he utilizado el .at construir, y trabajó como un encanto… df['x'].at['C'] = 10.0

  3. 76

    También puede usar un condicional de búsqueda utilizando .loc como se ve aquí:

    df.loc[df[<some_column_name>] == <condition>, [<another_column_name>]] = <value_to_add>

    donde <some_column_name es la columna que desea comprobar la <condition> variable en contra y <another_column_name> es la columna que desea agregar a (puede ser una nueva columna o uno que ya existe). <value_to_add> es el valor que desea agregar a la columna/fila.

    Este ejemplo no funciona precisamente con la pregunta en cuestión, pero podría ser útil para alguien desea añadir un valor específico en función de una condición.

    • la segunda columna debe ser sobre los soportes, de lo contrario, todas las columnas se sobrescribe con el valor. Como este: df.loc[df['age']==3, ['age-group']] = 'toddler'
    • Yo no puedo conseguir que esto funcione, cuando <some_column_name> es que mi índice (unixtime índice de decir) y estoy tratando de agregar una marca de tiempo que no salga todavía (es decir, una nueva marca de tiempo de lectura). Los pensamientos?
  4. 22

    Trate de usar df.loc[row_index,col_indexer] = value

    • Bienvenido a Desbordamiento de Pila! Por favor, considere la posibilidad de editar tu post para añadir más explicaciones acerca de lo que el código no hace y por qué se va a resolver el problema. Una respuesta que en su mayoría sólo contiene el código (incluso si se trata de trabajo) por lo general no va a ayudar a la OP a entender su problema. También se recomienda que usted no publicar una respuesta si es sólo una conjetura. Una buena respuesta tendrá una razón plausible de por qué podría resolver el OP del problema.
  5. 19

    Esta es la única cosa que trabajó para mí!

    df.loc['C', 'x'] = 10

    Aprender más acerca de .loc aquí.

    • hizo .loc reemplazar .iat/.at?
    • at Similar a loc, en que ambas ofrecen una etiqueta basada en búsquedas. Uso at si sólo necesita para obtener o establecer un único valor de un DataFrame o Serie. Desde padas doc
    • Bonito esto funcionó para mí cuando mi índice de elementos numéricos.
    • Esto no funciona para una mezcla de numéricos y de cadena de índices.
  6. 9

    .iat/.at es la buena solución.
    Suponiendo que tienes este sencillo data_frame:

       A   B   C
    0  1   8   4 
    1  3   9   6
    2  22 33  52

    si queremos modificar el valor de la celda [0,"A"] u puede utilizar una de esas solución :

    1. df.iat[0,0] = 2
    2. df.at[0,'A'] = 2

    Y aquí se muestra un ejemplo completo de cómo utilizar iat para obtener y establecer un valor de la celda :

    def prepossessing(df):
      for index in range(0,len(df)): 
          df.iat[index,0] = df.iat[index,0] * 2
      return df

    y_train antes :

        0
    0   54
    1   15
    2   15
    3   8
    4   31
    5   63
    6   11

    y_train después de llamar encantadora función que iat a cambio de multiplicar el valor de cada celda por 2:

         0
    0   108
    1   30
    2   30
    3   16
    4   62
    5   126
    6   22
  7. 6

    En mi ejemplo me acabo de cambiar de celda seleccionada

        for index, row in result.iterrows():
            if np.isnan(row['weight']):
                result.at[index, 'weight'] = 0.0

    ‘resultado’ es un dataField con la columna «peso»

  8. 4

    puede utilizar .iloc.

    df.iloc[[2], [0]] = 10
    • Este método no parece apoyar varios valores, por ejemplo, df.iloc[[2:8], [0]] = [2,3,4,5,6,7] que el método df.loc() hace de forma nativa.
  9. 3

    set_value() está en desuso.

    A partir de la liberación 0.23.4, Pandas «anuncia el futuro«…

    >>> df
                       Cars  Prices (U$)
    0               Audi TT        120.0
    1 Lamborghini Aventador        245.0
    2      Chevrolet Malibu        190.0
    >>> df.set_value(2, 'Prices (U$)', 240.0)
    __main__:1: FutureWarning: set_value is deprecated and will be removed in a future release.
    Please use .at[] or .iat[] accessors instead
    
                       Cars  Prices (U$)
    0               Audi TT        120.0
    1 Lamborghini Aventador        245.0
    2      Chevrolet Malibu        240.0

    Teniendo en cuenta este consejo, he aquí una demostración de cómo hacer uso de ellos:

    • por fila/columna entero posiciones

    >>> df.iat[1, 1] = 260.0
    >>> df
                       Cars  Prices (U$)
    0               Audi TT        120.0
    1 Lamborghini Aventador        260.0
    2      Chevrolet Malibu        240.0
    • por fila/columna de etiquetas

    >>> df.at[2, "Cars"] = "Chevrolet Corvette"
    >>> df
                      Cars  Prices (U$)
    0               Audi TT        120.0
    1 Lamborghini Aventador        260.0
    2    Chevrolet Corvette        240.0

    Referencias:

  10. 3

    A los valores de ajuste, uso:

    df.at[0, 'clm1'] = 0
    • El más rápido método recomendado para la configuración de las variables.
    • set_value, ix han quedado obsoletos.
    • Ninguna advertencia, a diferencia de iloc y loc
  11. 2

    Aquí es un resumen de la validez de las soluciones dadas por todos los usuarios, para marcos de datos indexados por entero y una cadena.

    df.iloc, df.loc y df.en el trabajo de ambos tipos de tramas de datos, df.iloc sólo funciona con la fila/columna entero índices, df.loc y df.en los apoyos para la configuración de los valores de uso de los nombres de columna y /o entero de los índices.

    Cuando el índice especificado no existe, tanto en el df.loc y df.en anexaría la que acaba de insertar filas o columnas a la existente estructura de datos, pero en el df.iloc levantaría «IndexError: posición indizadores están fuera de los límites». Un ejemplo de trabajo probado en Python 2.7 y 3.7 es como sigue:

    import numpy as np, pandas as pd
    
    df1 = pd.DataFrame(index=np.arange(3), columns=['x','y','z'])
    df1['x'] = ['A','B','C']
    df1.at[2,'y'] = 400
    
    # rows/columns specified does not exist, appends new rows/columns to existing data frame
    df1.at['D','w'] = 9000
    df1.loc['E','q'] = 499
    
    # using df[<some_column_name>] == <condition> to retrieve target rows
    df1.at[df1['x']=='B', 'y'] = 10000
    df1.loc[df1['x']=='B', ['z','w']] = 10000
    
    # using a list of index to setup values
    df1.iloc[[1,2,4], 2] = 9999
    df1.loc[[0,'D','E'],'w'] = 7500
    df1.at[[0,2,"D"],'x'] = 10
    df1.at[:, ['y', 'w']] = 8000
    
    df1
    >>> df1
         x     y     z     w      q
    0   10  8000   NaN  8000    NaN
    1    B  8000  9999  8000    NaN
    2   10  8000  9999  8000    NaN
    D   10  8000   NaN  8000    NaN
    E  NaN  8000  9999  8000  499.0
  12. 1

    Además de las respuestas de arriba, aquí es un punto de referencia para comparar diferentes maneras de agregar filas de datos de una ya existente dataframe. Se muestra que el uso o valor de ajuste es la forma más eficiente para grandes dataframes (al menos para estas condiciones de prueba).

    • Crear nuevos dataframe para cada fila y…
      • … anexar (13.0 s)
      • … concatenar (13.1 s)
    • Almacenar todas las nuevas filas en otro recipiente, en primer lugar, convertir a nueva dataframe una vez y anexar…
      • contenedor = listas de listas (2.0 s)
      • contenedor = diccionario de listas (1,9 s)
    • Asignar previamente todo el dataframe, iterar sobre nuevas filas y todas las columnas y llenar con
      • … en (0,6 s)
      • … set_value (0,4 s)

    Para la prueba, existente en un dataframe que comprende 100.000 filas y 1.000 columnas y azar numpy valores se utilizó. A este dataframe, 100 nuevas filas se han añadido.

    Código ver a continuación:

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    """
    Created on Wed Nov 21 16:38:46 2018
    @author: gebbissimo
    """
    import pandas as pd
    import numpy as np
    import time
    NUM_ROWS = 100000
    NUM_COLS = 1000
    data = np.random.rand(NUM_ROWS,NUM_COLS)
    df = pd.DataFrame(data)
    NUM_ROWS_NEW = 100
    data_tot = np.random.rand(NUM_ROWS + NUM_ROWS_NEW,NUM_COLS)
    df_tot = pd.DataFrame(data_tot)
    DATA_NEW = np.random.rand(1,NUM_COLS)
    #%% FUNCTIONS
    # create and append
    def create_and_append(df):
    for i in range(NUM_ROWS_NEW):
    df_new = pd.DataFrame(DATA_NEW)
    df = df.append(df_new)
    return df
    # create and concatenate
    def create_and_concat(df):
    for i in range(NUM_ROWS_NEW):
    df_new = pd.DataFrame(DATA_NEW)
    df = pd.concat((df, df_new))
    return df
    # store as dict and 
    def store_as_list(df):
    lst = [[] for i in range(NUM_ROWS_NEW)]
    for i in range(NUM_ROWS_NEW):
    for j in range(NUM_COLS):
    lst[i].append(DATA_NEW[0,j])
    df_new = pd.DataFrame(lst)
    df_tot = df.append(df_new)
    return df_tot
    # store as dict and 
    def store_as_dict(df):
    dct = {}
    for j in range(NUM_COLS):
    dct[j] = []
    for i in range(NUM_ROWS_NEW):
    dct[j].append(DATA_NEW[0,j])
    df_new = pd.DataFrame(dct)
    df_tot = df.append(df_new)
    return df_tot
    # preallocate and fill using .at
    def fill_using_at(df):
    for i in range(NUM_ROWS_NEW):
    for j in range(NUM_COLS):
    #print("i,j={},{}".format(i,j))
    df.at[NUM_ROWS+i,j] = DATA_NEW[0,j]
    return df
    # preallocate and fill using .at
    def fill_using_set(df):
    for i in range(NUM_ROWS_NEW):
    for j in range(NUM_COLS):
    #print("i,j={},{}".format(i,j))
    df.set_value(NUM_ROWS+i,j,DATA_NEW[0,j])
    return df
    #%% TESTS
    t0 = time.time()    
    create_and_append(df)
    t1 = time.time()
    print('Needed {} seconds'.format(t1-t0))
    t0 = time.time()    
    create_and_concat(df)
    t1 = time.time()
    print('Needed {} seconds'.format(t1-t0))
    t0 = time.time()    
    store_as_list(df)
    t1 = time.time()
    print('Needed {} seconds'.format(t1-t0))
    t0 = time.time()    
    store_as_dict(df)
    t1 = time.time()
    print('Needed {} seconds'.format(t1-t0))
    t0 = time.time()    
    fill_using_at(df_tot)
    t1 = time.time()
    print('Needed {} seconds'.format(t1-t0))
    t0 = time.time()    
    fill_using_set(df_tot)
    t1 = time.time()
    print('Needed {} seconds'.format(t1-t0))
  13. 0

    Si desea cambiar los valores no para toda la fila, pero sólo para algunas columnas:

    x = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
    x.iloc[1] = dict(A=10, B=-10)
  14. 0

    He probado y el resultado es df.set_value es poco más rápido, pero el método oficial de la df.at se ve como el más rápido no desuso manera de hacerlo.

    import numpy as np
    import pandas as pd
    df = pd.DataFrame(np.random.rand(100, 100))
    %timeit df.iat[50,50]=50 # ✓
    %timeit df.at[50,50]=50 #  ✔
    %timeit df.set_value(50,50,50) # will deprecate
    %timeit df.iloc[50,50]=50
    %timeit df.loc[50,50]=50
    7.06 µs ± 118 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
    5.52 µs ± 64.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
    3.68 µs ± 80.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
    98.7 µs ± 1.07 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    109 µs ± 1.42 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

    Nota: este es el valor de una sola célula. Para los vectores loc y iloc deben ser las mejores opciones, ya que son vectorizadas.

  15. -4

    Yo también estaba buscando este tema y me puse junto a un camino a recorrer a través de un DataFrame y actualizarlo con la búsqueda de valores de una segunda DataFrame. Aquí está mi código.

    src_df = pd.read_sql_query(src_sql,src_connection)
    for index1, row1 in src_df.iterrows():
    for index, row in vertical_df.iterrows():
    src_df.set_value(index=index1,col=u'etl_load_key',value=etl_load_key)
    if (row1[u'src_id'] == row['SRC_ID']) is True:
    src_df.set_value(index=index1,col=u'vertical',value=row['VERTICAL'])

Dejar respuesta

Please enter your comment!
Please enter your name here