python - functions - agregar una fila en un pandas.DataFrame
python pandas download windows (18)
Entiendo que los pandas están diseñados para cargar DataFrame
completamente poblado, pero necesito crear un DataFrame vacío y luego agregar filas, una por una . Cuál es la mejor manera de hacer esto ?
He creado con éxito un DataFrame vacío con:
res = DataFrame(columns=(''lib'', ''qty1'', ''qty2''))
Luego puedo agregar una nueva fila y rellenar un campo con:
res = res.set_value(len(res), ''qty1'', 10.0)
Funciona pero parece muy extraño: - / (falla al agregar valor de cadena)
¿Cómo puedo agregar una nueva fila a mi DataFrame (con tipo de columnas diferentes)?
Cree un nuevo registro (marco de datos) y añádalo a old_data_frame .
pase la lista de valores y los nombres de columna correspondientes para crear un nuevo_record (data_frame)
new_record = pd.DataFrame([[0,''abcd'',0,1,123]],columns=[''a'',''b'',''c'',''d'',''e''])
old_data_frame = pd.concat([old_data_frame,new_record])
Descubrió una manera simple y agradable:
>>> df
A B C
one 1 2 3
>>> df.loc["two"] = [4,5,6]
>>> df
A B C
one 1 2 3
two 4 5 6
Ejemplo en la respuesta de @Nasser:
>>> import pandas as pd
>>> import numpy as np
>>> df = pd.DataFrame(columns=[''lib'', ''qty1'', ''qty2''])
>>> for i in range(5):
>>> df.loc[i] = [np.random.randint(-1,1) for n in range(3)]
>>>
>>> print(df)
lib qty1 qty2
0 0 0 -1
1 -1 -1 1
2 1 -1 1
3 0 0 0
4 1 -1 -1
[5 rows x 3 columns]
En caso de que pueda obtener todos los datos para el marco de datos por adelantado, hay un enfoque mucho más rápido que agregar a un marco de datos:
- Cree una lista de diccionarios en los que cada diccionario corresponda a una fila de datos de entrada.
- Crear un marco de datos de esta lista.
Tuve una tarea similar para la cual agregar un fotograma a fila de datos tomó 30 minutos, y crear un marco de datos a partir de una lista de diccionarios completada en segundos.
rows_list = []
for row in input_rows:
dict1 = {}
# get input row in dictionary format
# key = col_name
dict1.update(blah..)
rows_list.append(dict1)
df = pd.DataFrame(rows_list)
Esta es la forma de agregar / agregar una fila en el marco de datos de pandas
def add_row(df, row):
df.loc[-1] = row
df.index = df.index + 1
return df.sort_index()
add_row(df, [1,2,3])
Se puede usar para insertar / agregar una fila en pandas vacías o pobladas. DataFrame
Esta no es una respuesta a la pregunta de OP, sino un ejemplo de juguete para ilustrar la respuesta de @ShikharDua anterior que me pareció muy útil.
Si bien este fragmento es trivial, en los datos reales tenía miles de filas y muchas columnas, y deseaba poder agrupar por columnas diferentes y luego realizar las estadísticas a continuación para más de una columna de taget. Por lo tanto, tener un método confiable para construir el marco de datos una fila a la vez fue una gran conveniencia. Gracias @ShikharDua!
import pandas as pd
BaseData = pd.DataFrame({ ''Customer'' : [''Acme'',''Mega'',''Acme'',''Acme'',''Mega'',''Acme''],
''Territory'' : [''West'',''East'',''South'',''West'',''East'',''South''],
''Product'' : [''Econ'',''Luxe'',''Econ'',''Std'',''Std'',''Econ'']})
BaseData
columns = [''Customer'',''Num Unique Products'', ''List Unique Products'']
rows_list=[]
for name, group in BaseData.groupby(''Customer''):
RecordtoAdd={} #initialise an empty dict
RecordtoAdd.update({''Customer'' : name}) #
RecordtoAdd.update({''Num Unique Products'' : len(pd.unique(group[''Product'']))})
RecordtoAdd.update({''List Unique Products'' : pd.unique(group[''Product''])})
rows_list.append(RecordtoAdd)
AnalysedData = pd.DataFrame(rows_list)
print(''Base Data : /n'',BaseData,''/n/n Analysed Data : /n'',AnalysedData)
Esto se encargará de agregar un elemento a un DataFrame vacío. El problema es que df.index.max () == nan para el primer índice:
df = pd.DataFrame(columns=[''timeMS'', ''accelX'', ''accelY'', ''accelZ'', ''gyroX'', ''gyroY'', ''gyroZ''])
df.loc[0 if math.isnan(df.index.max()) else df.index.max() + 1] = [x for x in range(7)]
Ha pasado mucho tiempo, pero también enfrenté el mismo problema. Y encontré aquí muchas respuestas interesantes. Así que estaba confundido qué método utilizar.
En el caso de agregar muchas filas al marco de datos, me interesa la velocidad de rendimiento . Así que probé los 3 métodos más populares y comprobé su velocidad.
RENDIMIENTO DE VELOCIDAD
- Usando .append ( respuesta de NPE )
- Usando .loc ( la respuesta de fred y la respuesta de FooBar )
- Usando dict y crea DataFrame al final ( la respuesta de ShikharDua )
Resultados (en segundos):
Adding 1000 rows 5000 rows 10000 rows
.append 1.04 4.84 9.56
.loc 1.16 5.59 11.50
dict 0.23 0.26 0.34
Así que uso la adición a través del diccionario para mí.
Código:
import pandas
import numpy
import time
numOfRows = 10000
startTime = time.perf_counter()
df1 = pandas.DataFrame(numpy.random.randint(100, size=(5,5)), columns=[''A'', ''B'', ''C'', ''D'', ''E''])
for i in range( 1,numOfRows):
df1 = df1.append( dict( (a,numpy.random.randint(100)) for a in [''A'',''B'',''C'',''D'',''E'']), ignore_index=True)
print(''Elapsed time: {:6.3f} seconds for {:d} rows''.format(time.perf_counter() - startTime, numOfRows))
startTime = time.perf_counter()
df2 = pandas.DataFrame(numpy.random.randint(100, size=(5,5)), columns=[''A'', ''B'', ''C'', ''D'', ''E''])
for i in range( 1,numOfRows):
df2.loc[df2.index.max()+1] = numpy.random.randint(100, size=(1,5))[0]
print(''Elapsed time: {:6.3f} seconds for {:d} rows''.format(time.perf_counter() - startTime, numOfRows))
startTime = time.perf_counter()
row_list = []
for i in range (0,5):
row_list.append(dict( (a,numpy.random.randint(100)) for a in [''A'',''B'',''C'',''D'',''E'']))
for i in range( 1,numOfRows):
dict1 = dict( (a,numpy.random.randint(100)) for a in [''A'',''B'',''C'',''D'',''E''])
row_list.append(dict1)
df3 = pandas.DataFrame(row_list, columns=[''A'',''B'',''C'',''D'',''E''])
print(''Elapsed time: {:6.3f} seconds for {:d} rows''.format(time.perf_counter() - startTime, numOfRows))
PD: Creo que mi realización no es perfecta, y tal vez haya alguna optimización.
Hazlo simple. Al tomar la lista como entrada, que se agregará como fila en el marco de datos:
import pandas as pd
res = pd.DataFrame(columns=(''lib'', ''qty1'', ''qty2''))
for i in range(5):
res_list = list(map(int, input().split()))
res = res.append(pd.Series(res_list,index=[''lib'',''qty1'',''qty2'']), ignore_index=True)
Otra forma de hacerlo (probablemente no muy performante):
# add a row
def add_row(df, row):
colnames = list(df.columns)
ncol = len(colnames)
assert ncol == len(row), "Length of row must be the same as width of DataFrame: %s" % row
return df.append(pd.DataFrame([row], columns=colnames))
También puede mejorar la clase DataFrame de esta manera:
import pandas as pd
def add_row(self, row):
self.loc[len(self.index)] = row
pd.DataFrame.add_row = add_row
Para una adición eficiente, vea Cómo agregar una fila adicional a un marco de datos de pandas y Configuración con ampliación .
Agregue filas a través de loc/ix
en datos de índice de clave no existentes . p.ej :
In [1]: se = pd.Series([1,2,3])
In [2]: se
Out[2]:
0 1
1 2
2 3
dtype: int64
In [3]: se[5] = 5.
In [4]: se
Out[4]:
0 1.0
1 2.0
2 3.0
5 5.0
dtype: float64
O:
In [1]: dfi = pd.DataFrame(np.arange(6).reshape(3,2),
.....: columns=[''A'',''B''])
.....:
In [2]: dfi
Out[2]:
A B
0 0 1
1 2 3
2 4 5
In [3]: dfi.loc[:,''C''] = dfi.loc[:,''A'']
In [4]: dfi
Out[4]:
A B C
0 0 1 0
1 2 3 2
2 4 5 4
In [5]: dfi.loc[3] = 5
In [6]: dfi
Out[6]:
A B C
0 0 1 0
1 2 3 2
2 4 5 4
3 5 5 5
Podría usar pandas.concat()
o DataFrame.append()
. Para detalles y ejemplos, vea Combinar, unir y concatenar .
Por el bien de la manera Pythonic, aquí agregue mi respuesta:
res = pd.DataFrame(columns=(''lib'', ''qty1'', ''qty2''))
res = res.append([{''qty1'':10.0}], ignore_index=True)
print(res.head())
lib qty1 qty2
0 NaN 10.0 NaN
Puede agregar una sola fila como diccionario usando la opción ignore_index
.
>>> f = pandas.DataFrame(data = {''Animal'':[''cow'',''horse''], ''Color'':[''blue'', ''red'']})
>>> f
Animal Color
0 cow blue
1 horse red
>>> f.append({''Animal'':''mouse'', ''Color'':''black''}, ignore_index=True)
Animal Color
0 cow blue
1 horse red
2 mouse black
Si conoce el número de entradas ex ante, debe preasignar el espacio proporcionando también el índice (tomando el ejemplo de datos de una respuesta diferente):
import pandas as pd
import numpy as np
# we know we''re gonna have 5 rows of data
numberOfRows = 5
# create dataframe
df = pd.DataFrame(index=np.arange(0, numberOfRows), columns=(''lib'', ''qty1'', ''qty2'') )
# now fill it up row by row
for x in np.arange(0, numberOfRows):
#loc or iloc both work here since the index is natural numbers
df.loc[x] = [np.random.randint(-1,1) for n in range(3)]
In[23]: df
Out[23]:
lib qty1 qty2
0 -1 -1 -1
1 0 0 0
2 -1 0 -1
3 0 -1 0
4 -1 0 0
Comparación de velocidad
In[30]: %timeit tryThis() # function wrapper for this answer
In[31]: %timeit tryOther() # function wrapper without index (see, for example, @fred)
1000 loops, best of 3: 1.23 ms per loop
100 loops, best of 3: 2.31 ms per loop
Y, a partir de los comentarios, con un tamaño de 6000, la diferencia de velocidad es aún mayor:
Aumentar el tamaño de la matriz (12) y el número de filas (500) hace que la diferencia de velocidad sea más sorprendente: 313 ms frente a 2,29 s.
También puede crear una lista de listas y convertirla en un marco de datos.
import pandas as pd
rows = []
columns = [''i'',''double'',''square'']
for i in range(6):
row = [i, i*2, i*i]
rows.append(row)
df = pd.DataFrame(rows, columns=columns)
dando
i double square 0 0 0 0 1 1 2 1 2 2 4 4 3 3 6 9 4 4 8 16 5 5 10 25
import pandas as pd
t1=pd.DataFrame()
for i in range(len(the number of rows)):
#add rows as columns
t1[i]=list(rows)
t1=t1.transpose()
t1.columns=list(columns)
mycolumns = [''A'', ''B'']
df = pd.DataFrame(columns=mycolumns)
rows = [[1,2],[3,4],[5,6]]
for row in rows:
df.loc[len(df)] = row