Maak een Pandas-dataframe door één rij tegelijk toe te voegen

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:

  1. Maak een lijst met woordenboeken waarin elk woordenboek overeenkomt met een invoergegevensrij.
  2. 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

  1. Gebruik .append (NPE’s antwoord)
  2. Gebruik van .loc (antwoord van Fred)
  3. Gebruik van .loc met vooraf toewijzen (FooBar’s antwoord)
  4. 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.

  1. Het is altijd goedkoper/sneller om een ​​lijst toe te voegen en in één keer een DataFrame te maken.
  2. Lijsten nemen minder geheugen in beslag en zijn een veel lichtere gegevensstructuur om mee te werken, toe te voegen en te verwijderen.
  3. dtypes worden automatisch afgeleid voor uw gegevens. Aan de andere kant maakt het maken van een leeg frame van NaN’s ze automatisch object, wat niet goed is.
  4. 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

  1. append of concat in een lus

    append en concat 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)
    
  2. 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.

voer hier de afbeeldingsbeschrijving in

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

LEAVE A REPLY

Please enter your comment!
Please enter your name here

15 − 11 =

Other episodes