Ik begrijp dat Pandas is ontworpen om een volledig gevuld DataFrame
te laden, maar ik moet een leeg DataFrame maken en vervolgens rijen toevoegen, één voor één.
Wat is de beste manier om dit te doen?
Ik heb met succes een leeg DataFrame gemaakt met:
res = DataFrame(columns=('lib', 'qty1', 'qty2'))
Dan kan ik een nieuwe rij toevoegen en een veld vullen met:
res = res.set_value(len(res), 'qty1', 10.0)
Het werkt, maar het lijkt erg vreemd :-/ (Het toevoegen van een stringwaarde lukt niet.)
Hoe kan ik een nieuwe rij aan mijn DataFrame toevoegen (met een ander type kolom)?
Antwoord 1, autoriteit 100%
U kunt df.loc[i]
gebruiken, waarbij de rij met index i
is wat u specificeert in het dataframe.
>>> import pandas as pd
>>> from numpy.random import randint
>>> df = pd.DataFrame(columns=['lib', 'qty1', 'qty2'])
>>> for i in range(5):
>>> df.loc[i] = ['name' + str(i)] + list(randint(10, size=2))
>>> df
lib qty1 qty2
0 name0 3 3
1 name1 2 4
2 name2 2 8
3 name3 2 1
4 name4 9 6
Antwoord 2, autoriteit 84%
Als u alle gegevens voor het dataframe vooraf kunt krijgen, is er een veel snellere aanpak dan het toevoegen aan een dataframe:
- Maak een lijst met woordenboeken waarin elk woordenboek overeenkomt met een invoergegevensrij.
- Maak een dataframe van deze lijst.
Ik had een vergelijkbare taak waarbij het rij voor rij toevoegen aan een dataframe 30 minuten duurde en het maken van een dataframe uit een lijst met woordenboeken die binnen enkele seconden voltooid was.
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)
Antwoord 3, autoriteit 41%
U kunt pandas.concat()
of DataFrame.append()
gebruiken. Voor details en voorbeelden, zie Samenvoegen, samenvoegen en samenvoegen.
Antwoord 4, autoriteit 39%
In het geval van het toevoegen van veel rijen aan het dataframe, ben ik geïnteresseerd in de prestaties. Dus ik probeerde de vier meest populaire methoden en controleerde hun snelheid.
Prestaties
- Gebruik .append (NPE’s antwoord)
- Gebruik van .loc (antwoord van Fred)
- Gebruik van .loc met vooraf toewijzen (FooBar’s antwoord)
- Dict gebruiken en uiteindelijk een DataFrame maken (ShikharDua’s antwoord)
Runtime-resultaten (in seconden):
Aanpak | 1000 rijen | 5000 rijen | 10 000 rijen |
---|---|---|---|
.toevoegen | 0,69 | 3.39 | 6,78 |
.loc zonder voortoewijzing | 0,74 | 3.90 | 8,35 |
.loc met prealloc | 0,24 | 2,58 | 8,70 |
dict | 0,012 | 0,046 | 0,084 |
Antwoord 5, autoriteit 22%
Kweek NOOIT een DataFrame!
Ja, mensen hebben al uitgelegd dat je NOOIT een DataFrame moet laten groeien, en dat je je gegevens aan een lijst moet toevoegen en deze aan het einde eenmaal naar een DataFrame moet converteren. Maar begrijp je waarom?
Hier zijn de belangrijkste redenen, overgenomen uit mijn post hier.
- Het is altijd goedkoper/sneller om een lijst toe te voegen en in één keer een DataFrame te maken.
- Lijsten nemen minder geheugen in beslag en zijn een veel lichtere gegevensstructuur om mee te werken, toe te voegen en te verwijderen.
dtypes
worden automatisch afgeleid voor uw gegevens. Aan de andere kant maakt het maken van een leeg frame van NaN’s ze automatischobject
, wat niet goed is.- Er wordt automatisch een index voor u gemaakt, in plaats van dat u ervoor moet zorgen dat u de juiste index toewijst aan de rij die u toevoegt.
Dit is de juiste manier om uw gegevens te verzamelen
data = []
for a, b, c in some_function_that_yields_data():
data.append([a, b, c])
df = pd.DataFrame(data, columns=['A', 'B', 'C'])
Deze opties zijn verschrikkelijk
-
append
ofconcat
in een lusappend
enconcat
zijn niet inherent slecht op zichzelf staand. De
het probleem begint wanneer je ze iteratief in een lus roept – dit
resulteert in kwadratisch geheugengebruik.# Creates empty DataFrame and appends df = pd.DataFrame(columns=['A', 'B', 'C']) for a, b, c in some_function_that_yields_data(): df = df.append({'A': i, 'B': b, 'C': c}, ignore_index=True) # This is equally bad: # df = pd.concat( # [df, pd.Series({'A': i, 'B': b, 'C': c})], # ignore_index=True)
-
Leeg dataframe van NaN’s
Maak nooit een DataFrame van NaN’s omdat de kolommen worden geïnitialiseerd met
object
(traag, niet-vectoriseerbaar dtype).# Creates DataFrame of NaNs and overwrites values. df = pd.DataFrame(columns=['A', 'B', 'C'], index=range(5)) for a, b, c in some_function_that_yields_data(): df.loc[len(df)] = [a, b, c]
Het bewijs zit in de pudding
Het timen van deze methoden is de snelste manier om te zien hoeveel ze verschillen in geheugen en bruikbaarheid.
Benchmarkingscode ter referentie.
Het zijn berichten als deze die me eraan herinneren waarom ik deel uitmaak van deze community. Mensen begrijpen hoe belangrijk het is om mensen te leren het juiste antwoord te krijgen met de juiste code, niet het juiste antwoord met verkeerde code. Nu zou je kunnen beweren dat het geen probleem is om loc
of append
te gebruiken als je maar één rij aan je DataFrame toevoegt. mensen kijken echter vaak naar deze vraag om meer dan slechts één rij toe te voegen – vaak is de vereiste om iteratief een rij toe te voegen in een lus met behulp van gegevens die afkomstig zijn van een functie ( zie gerelateerde vraag). In dat geval is het belangrijk om te begrijpen dat het iteratief laten groeien van een DataFrame geen goed idee is.
Antwoord 6, autoriteit 16%
Als u het aantal items vooraf weet, moet u de ruimte vooraf toewijzen door ook de index op te geven (door het gegevensvoorbeeld uit een ander antwoord te nemen):
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
Snelheidsvergelijking
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
En – vanaf de opmerkingen – met een grootte van 6000 wordt het snelheidsverschil nog groter:
Het vergroten van de array (12) en het aantal rijen (500) maakt
het snelheidsverschil opvallender: 313ms vs 2.29s
Antwoord 7, autoriteit 12%
mycolumns = ['A', 'B']
df = pd.DataFrame(columns=mycolumns)
rows = [[1,2],[3,4],[5,6]]
for row in rows:
df.loc[len(df)] = row
Antwoord 8, autoriteit 10%
Je kunt een enkele rij als woordenboek toevoegen met de optie 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
Antwoord 9, autoriteit 10%
Voor efficiënt toevoegen, zie Een extra rij toevoegen aan een pandas-dataframe en Instelling met vergroting.
Voeg rijen toe via loc/ix
op niet bestaande sleutelindexgegevens. Bijvoorbeeld:
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
Of:
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
Antwoord 10, autoriteit 6%
Omwille van een Pythonische manier:
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
Antwoord 11, autoriteit 4%
Je kunt ook een lijst met lijsten maken en deze converteren naar een dataframe –
import pandas as pd
columns = ['i','double','square']
rows = []
for i in range(6):
row = [i, i*2, i*i]
rows.append(row)
df = pd.DataFrame(rows, columns=columns)
geven
ik verdubbel vierkant 0 0 0 0 1 1 2 1 2 2 4 4 3 3 6 9 4 4 8 16 5 5 10 25
Antwoord 12, autoriteit 2%
Ik heb een eenvoudige en leuke manier bedacht:
>>> 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
Let op het voorbehoud met prestaties zoals vermeld in de opmerkingen.
Antwoord 13, autoriteit 2%
Dit is geen antwoord op de OP-vraag, maar een speelgoedvoorbeeld om ShikharDua’s antwoord dat ik erg nuttig vond.
Hoewel dit fragment triviaal is, had ik in de werkelijke gegevens duizenden rijen en veel kolommen, en ik wilde in staat zijn te groeperen op verschillende kolommen en dan de onderstaande statistieken voor meer dan één doelkolom uit te voeren. Het was dus een groot gemak om een betrouwbare methode te hebben om het dataframe rij voor rij te bouwen. Bedankt 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)
Antwoord 14
U kunt een generatorobject gebruiken om een dataframe te maken, dat efficiënter is dan de lijst.
num = 10
# Generator function to generate generator object
def numgen_func(num):
for i in range(num):
yield ('name_{}'.format(i), (i*i), (i*i*i))
# Generator expression to generate generator object (Only once data get populated, can not be re used)
numgen_expression = (('name_{}'.format(i), (i*i), (i*i*i)) for i in range(num) )
df = pd.DataFrame(data=numgen_func(num), columns=('lib', 'qty1', 'qty2'))
Om onbewerkt toe te voegen aan een bestaand DataFrame kunt u de append-methode gebruiken.
df = df.append([{ 'lib': "name_20", 'qty1': 20, 'qty2': 400 }])
Antwoord 15
Maak een nieuw record (dataframe) en voeg toe aan old_data_frame.
Geef een lijst met waarden en de bijbehorende kolom namen door om een new_record (data_frame) te maken:
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])
Antwoord 16
Hier is de manier om een rij toe te voegen/toe te voegen in een Pandas DataFrame
:
def add_row(df, row):
df.loc[-1] = row
df.index = df.index + 1
return df.sort_index()
add_row(df, [1,2,3])
Het kan worden gebruikt om een rij in te voegen/toe te voegen in een leeg of gevuld Pandas DataFrame.
Antwoord 17
In plaats van een lijst met woordenboeken zoals in ShikharDua’s antwoord, we kunnen onze tabel ook weergeven als een woordenboek van lijsten, waarbij elke lijst één kolom in rijvolgorde opslaat, aangezien we onze kolommen van tevoren kennen. Aan het einde bouwen we ons DataFrame één keer op.
Voor c kolommen en n rijen gebruikt dit één woordenboek en c lijsten, versus één lijst en n woordenboeken. Bij de methode lijst met woordenboeken worden alle sleutels in elk woordenboek opgeslagen en moet voor elke rij een nieuw woordenboek worden gemaakt. Hier voegen we alleen lijsten toe, wat een constante tijd is en in theorie erg snel.
# Current data
data = {"Animal":["cow", "horse"], "Color":["blue", "red"]}
# Adding a new row (be careful to ensure every column gets another value)
data["Animal"].append("mouse")
data["Color"].append("black")
# At the end, construct our DataFrame
df = pd.DataFrame(data)
# Animal Color
# 0 cow blue
# 1 horse red
# 2 mouse black
Antwoord 18
Als je altijd een nieuwe rij aan het einde wilt toevoegen, gebruik dan dit:
df.loc[len(df)] = ['name5', 9, 0]
Antwoord 19
Als u een rij aan het einde wilt toevoegen, voegt u deze toe als een lijst:
valuestoappend = [va1, val2, val3]
res = res.append(pd.Series(valuestoappend, index = ['lib', 'qty1', 'qty2']), ignore_index = True)
Antwoord 20
Een andere manier om het te doen (waarschijnlijk niet erg performant):
# 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))
U kunt de klasse DataFrame ook als volgt verbeteren:
import pandas as pd
def add_row(self, row):
self.loc[len(self.index)] = row
pd.DataFrame.add_row = add_row
Antwoord 21
Alles wat je nodig hebt is loc[df.shape[0]]
of loc[len(df)]
# Assuming your df has 4 columns (str, int, str, bool)
df.loc[df.shape[0]] = ['col1Value', 100, 'col3Value', False]
of
df.loc[len(df)] = ['col1Value', 100, 'col3Value', False]
Antwoord 22
initial_data = {'lib': np.array([1,2,3,4]), 'qty1': [1,2,3,4], 'qty2': [1,2,3,4]}
df = pd.DataFrame(initial_data)
df
lib qty1 qty2
0 1 1 1
1 2 2 2
2 3 3 3
3 4 4 4
val_1 = [10]
val_2 = [14]
val_3 = [20]
df.append(pd.DataFrame({'lib': val_1, 'qty1': val_2, 'qty2': val_3}))
lib qty1 qty2
0 1 1 1
1 2 2 2
2 3 3 3
3 4 4 4
0 10 14 20
U kunt een for-lus gebruiken om door waarden te bladeren of u kunt arrays van waarden toevoegen.
val_1 = [10, 11, 12, 13]
val_2 = [14, 15, 16, 17]
val_3 = [20, 21, 22, 43]
df.append(pd.DataFrame({'lib': val_1, 'qty1': val_2, 'qty2': val_3}))
lib qty1 qty2
0 1 1 1
1 2 2 2
2 3 3 3
3 4 4 4
0 10 14 20
1 11 15 21
2 12 16 22
3 13 17 43
Antwoord 23
Maak het eenvoudig. Door een lijst als invoer te nemen die als een rij in het dataframe wordt toegevoegd:
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)
Antwoord 24
Als je een dataframe df
hebt en een lijst new_list
als nieuwe rij wilt toevoegen aan df
, je kunt gewoon doen:
df.loc[len(df)] = new_list
Als u een nieuw dataframe new_df
onder dataframe df
wilt toevoegen, kunt u het volgende gebruiken:
df.append(new_df)
Antwoord 25
We zien vaak de constructie df.loc[subscript] = …
om aan één DataFrame-rij toe te wijzen. Mikhail_Sam heeft benchmarks gepost die onder andere deze constructie bevatten, evenals de methode die dict gebruikt en uiteindelijk DataFrame maken . Die laatste vond hij verreweg de snelste.
Maar als we de df3.loc[i] = …
(met vooraf toegewezen DataFrame) in zijn code vervangen door df3.values[i] = …
, is de uitkomst verandert aanzienlijk, in die zin dat die methode vergelijkbaar is met die met dict. We moeten dus vaker rekening houden met het gebruik van df.values[subscript] = …
. Houd er echter rekening mee dat .values
een op nul gebaseerd subscript heeft, dat kan verschillen van de DataFrame.index.
Antwoord 26
pandas.DataFrame.append
DataFrame.append(self, other, negeer_index=False, confirm_integrity=False, sort=False) > ‘DataFrame’
Code
df = pd.DataFrame([[1, 2], [3, 4]], columns=list('AB'))
df2 = pd.DataFrame([[5, 6], [7, 8]], columns=list('AB'))
df.append(df2)
Met negeer_index ingesteld op True:
df.append(df2, ignore_index=True)
Antwoord 27
Hiervoor kunt u twee DataFrames samenvoegen. Ik kwam eigenlijk dit probleem tegen om een nieuwe rij toe te voegen aan een bestaand DataFrame met een karakterindex (niet numeriek).
Dus ik heb de gegevens voor een nieuwe rij in een duct() en index in een lijst ingevoerd.
new_dict = {put input for new row here}
new_list = [put your index here]
new_df = pd.DataFrame(data=new_dict, index=new_list)
df = pd.concat([existing_df, new_df])
Antwoord 28
Als alle gegevens in uw dataframe hetzelfde dtype hebben, kunt u een NumPy-array gebruiken. U kunt rijen rechtstreeks in de vooraf gedefinieerde array schrijven en deze aan het einde converteren naar een dataframe.
Het lijkt zelfs sneller te gaan dan het converteren van een lijst met dictaten.
import pandas as pd
import numpy as np
from string import ascii_uppercase
startTime = time.perf_counter()
numcols, numrows = 5, 10000
npdf = np.ones((numrows, numcols))
for row in range(numrows):
npdf[row, 0:] = np.random.randint(0, 100, (1, numcols))
df5 = pd.DataFrame(npdf, columns=list(ascii_uppercase[:numcols]))
print('Elapsed time: {:6.3f} seconds for {:d} rows'.format(time.perf_counter() - startTime, numOfRows))
print(df5.shape)
Antwoord 29
Dit codefragment gebruikt een lijst met woordenboeken om het dataframe bij te werken. Het voegt toe aan ShikharDua’s en Mikhail_Sam’s antwoorden.
import pandas as pd
colour = ["red", "big", "tasty"]
fruits = ["apple", "banana", "cherry"]
dict1={}
feat_list=[]
for x in colour:
for y in fruits:
# print(x, y)
dict1 = dict([('x',x),('y',y)])
# print(f'dict 1 {dict1}')
feat_list.append(dict1)
# print(f'feat_list {feat_list}')
feat_df=pd.DataFrame(feat_list)
feat_df.to_csv('feat1.csv')
Antwoord 30
Voordat we een rij gaan toevoegen, moeten we het dataframe converteren naar een woordenboek. Daar zie je de sleutels als kolommen in het dataframe en de waarden van de kolommen worden weer opgeslagen in het woordenboek, maar daar is de sleutel voor elke kolom het indexnummer in het dataframe.
Dat idee brengt me ertoe de onderstaande code te schrijven.
df2 = df.to_dict()
values = ["s_101", "hyderabad", 10, 20, 16, 13, 15, 12, 12, 13, 25, 26, 25, 27, "good", "bad"] # This is the total row that we are going to add
i = 0
for x in df.columns: # Here df.columns gives us the main dictionary key
df2[x][101] = values[i] # Here the 101 is our index number. It is also the key of the sub dictionary
i += 1