Boş bir Panda DataFrame oluşturma, sonra doldurma?


463

Buradaki pandalar DataFrame belgelerinden başlıyorum: http://pandas.pydata.org/pandas-docs/stable/dsintro.html

Yinelenen DataFrame bir zaman serisi tür hesaplama değerleri ile doldurmak istiyorum. Temel olarak, DataFrame'i A, B sütunları ve zaman damgası satırları, tümü 0 veya tümü NaN ile başlatmak istiyorum.

Daha sonra başlangıç ​​değerleri ekler ve bu veriyi, önceki satırdan yeni satırı hesaplayarak söylerdim row[A][t] = row[A][t-1]+1.

Şu anda aşağıdaki gibi kod kullanıyorum, ama çirkin hissediyorum ve doğrudan bir DataFrame ile bunu yapmak için bir yol olmalı veya genel olarak daha iyi bir yol olmalı. Not: Python 2.7 kullanıyorum.

import datetime as dt
import pandas as pd
import scipy as s

if __name__ == '__main__':
    base = dt.datetime.today().date()
    dates = [ base - dt.timedelta(days=x) for x in range(0,10) ]
    dates.sort()

    valdict = {}
    symbols = ['A','B', 'C']
    for symb in symbols:
        valdict[symb] = pd.Series( s.zeros( len(dates)), dates )

    for thedate in dates:
        if thedate > dates[0]:
            for symb in valdict:
                valdict[symb][thedate] = 1+valdict[symb][thedate - dt.timedelta(days=1)]

    print valdict

6
Asla bir DataFrame büyütmeyin! Python listesine eklemek ve daha sonra hem bellek hem de performans açısından listeyi DataFrame'e dönüştürmek her zaman daha ucuzdur.
cs95

@ cs95 .appendPD ile liste ekleme arasında işlevsel olarak fark nedir ? .appendPandalarda bütün veri kümesini yeni bir nesneye kopyalar biliyorum p pitonlar farklı çalışır mı?
Lamma

@Lamma lütfen aşağıdaki cevabımda ayrıntıları bulabilirsiniz. Df'ye eklenirken, bellekte her seferinde mevcut olanı kullanmak yerine her seferinde yeni bir DataFrame oluşturulur;
cs95

Yanıtlar:


330

İşte size birkaç öneri:

date_rangeDizin için kullanın :

import datetime
import pandas as pd
import numpy as np

todays_date = datetime.datetime.now().date()
index = pd.date_range(todays_date-datetime.timedelta(10), periods=10, freq='D')

columns = ['A','B', 'C']

Not: yazarak boş bir DataFrame ( NaNler) oluşturabiliriz :

df_ = pd.DataFrame(index=index, columns=columns)
df_ = df_.fillna(0) # with 0s rather than NaNs

Veriler için bu tür hesaplamaları yapmak üzere bir numpy dizisi kullanın:

data = np.array([np.arange(10)]*3).T

Bu nedenle DataFrame'i oluşturabiliriz:

In [10]: df = pd.DataFrame(data, index=index, columns=columns)

In [11]: df
Out[11]: 
            A  B  C
2012-11-29  0  0  0
2012-11-30  1  1  1
2012-12-01  2  2  2
2012-12-02  3  3  3
2012-12-03  4  4  4
2012-12-04  5  5  5
2012-12-05  6  6  6
2012-12-06  7  7  7
2012-12-07  8  8  8
2012-12-08  9  9  9

2
pd.date_range () benim için çalışmıyor. DateRange (eclipse's autocompletion itibaren) ile denedim, ama tarih biçimi olarak dizeleri ile çalışır, değil mi? Genel yaklaşım olsa çalışır (Ben indeks başka bir şeye değiştirdim).
Matthias Kauer

2
date_range, datetime dizinleri oluşturmak için bir fabrika işlevidir ve 0.8.0'da yeni bir özellikti , kesinlikle en son kararlı sürüme (0.9.1) yükseltmeyi tavsiye ederim, birçok hata düzeltmesi ve yeni özellik var. :)
Andy Hayden

26
Deneyimlerime göre, NaN'lerle dolu gerekli boyutta bir veri çerçevesi oluşturmak ve sonra değerlerle doldurmak, indexx 0boyutlarına ( columns = []) sahip bir veri çerçevesi oluşturmaktan ve bir döngünün her dönüşüne bir sütun eklemekten çok daha yavaştır . Yani df[col_name] = pandas.Series([...])sütun isimleri arasında yinelenen bir döngüde. İlk durumda, sadece bellek ayırma işlemi zaman almaz, aynı zamanda NaN'leri yeni değerlerle değiştirmek son derece yavaş görünür.
deeenes

5
@deeenes kesinlikle. bu cevap muhtemelen bunu daha net hale getirmelidir - çok nadiren (eğer varsa) boş bir Veri Çerçevesi (NaN) oluşturmak istiyorsunuz.
Andy Hayden

1
Bu cevaba göre stackoverflow.com/a/30267881/2302569 fillna sonucunu atamanız veya param'i inplace = True
JayJay

169

Yalnızca boş bir veri çerçevesi oluşturmak ve daha sonra gelen bazı veri çerçeveleriyle doldurmak istiyorsanız şunu deneyin:

newDF = pd.DataFrame() #creates a new dataframe that's empty
newDF = newDF.append(oldDF, ignore_index = True) # ignoring index is optional
# try printing some data from newDF
print newDF.head() #again optional 

Bu örnekte , yeni bir veri çerçevesi oluşturmak için bu pandalar belgesini kullanıyorum ve daha sonra oldDF'den gelen verilerle newDF'ye yazmak için append kullanıyorum .

Birden fazla oldDF'den bu newDF'ye yeni veriler eklemeye devam etmem gerekiyorsa, pandas.DataFrame.append ()


14
Unutmayın append(ve benzer şekilde concat) veri kümesinin tamamını her seferinde yeni bir nesneye kopyalar, bu nedenle yineleme ve ekleme işlemlerinin büyük bir performans isabetine neden olabileceğini ve bunun neden olacağını unutmayın. daha fazla bilgi için bakınız: pandas.pydata.org/pandas-docs/stable/merging.html
MoustafaAAtta

4
@MoustafaAAtta Yinelemeli verileri veri çerçevesine eklemenin alternatifleri nelerdir?
MysteryGuy

2
@MoustafaAAtta Fred bu yazıda cevap veriyor mu? Stackoverflow.com/questions/10715965/… bu bakış açısından daha mı iyi?
MysteryGuy

Bir veri çerçevesine yalnızca satırlar ekleyebilirsiniz, yine de yeni bir nesne oluşturacaktır, ancak daha küçük veri kümeleri için yararlı olabilir. pandas.pydata.org/pandas-docs/stable/user_guide/…
geekidharsh

137

DataFrame Oluşturmanın Doğru Yolu ™

TLDR; (sadece kalın metni okuyun)

Buradaki yanıtların çoğu size boş bir DataFrame'in nasıl oluşturulacağını ve dolduracağını söyleyecektir, ancak kimse bunun kötü bir şey olduğunu söylemeyecektir.

İşte tavsiyem: Çalışmanız gereken tüm verilere sahip olduğunuzdan emin olana kadar bekleyin. Verilerinizi toplamak için bir liste kullanın, ardından hazır olduğunuzda bir DataFrame başlatın.

data = []
for a, b, c in some_function_that_yields_data():
    data.append([a, b, c])

df = pd.DataFrame(data, columns=['A', 'B', 'C'])

Öyle bir listeye ekler ve tek seferde bir DataFrame oluşturmak için her zaman daha ucuz o tekrar tekrar kendisine boş bir DataFrame (veya NaN'ler ait biri) ve append yaratmaktır daha. Listeler de daha az bellek kaplar ve çalışmak , eklemek ve kaldırmak (gerekirse) için çok daha hafif bir veri yapısıdır .

Bu yöntemin diğer avantajı dtypesotomatik olarak çıkarılır ( objecthepsine atamak yerine ).

Geçen avantaj olduğunu bir RangeIndexotomatik veri için oluşturulan yaklaşık endişe için bir daha az şey (kötü bakmak yani, appendve loc, uygun şekilde indeksi ele gerektiren hem de elemanlarını göreceksiniz aşağıda yöntemlerle).


YAPMAMANIZ GEREKENLER

appendveya concatbir döngü içinde

İşte yeni başlayanlardan gördüğüm en büyük hata:

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) # yuck
    # or similarly,
    # df = pd.concat([df, pd.Series({'A': i, 'B': b, 'C': c})], ignore_index=True)

Bellek, sahip olduğunuz her işlem appendveya concatişlem için yeniden ayrılır . Bunu bir döngü ile birleştirin ve ikinci dereceden karmaşıklık işleminiz var . Gönderen df.appenddoc sayfa :

Bir DataFrame'e satırları art arda eklemek, tek bir birleştirme işleminden daha fazla hesaplama açısından yoğun olabilir. Daha iyi bir çözüm, bu satırları bir listeye eklemek ve ardından listeyi orijinal DataFrame ile bir kerede birleştirmektir.

İle ilişkili diğer bir hata df.append, kullanıcıların ekleme eklemeyi unutma eğiliminde olmalarının yerinde bir işlev olmamasıdır , bu nedenle sonuç geri atanmalıdır. Ayrıca türler hakkında endişelenmelisiniz:

df = pd.DataFrame(columns=['A', 'B', 'C'])
df = df.append({'A': 1, 'B': 12.3, 'C': 'xyz'}, ignore_index=True)

df.dtypes
A     object   # yuck!
B    float64
C     object
dtype: object

Nesne sütunlarıyla uğraşmak asla iyi bir şey değildir, çünkü pandalar bu sütunlardaki işlemleri vektörleştiremez. Düzeltmek için bunu yapmanız gerekecek:

df.infer_objects().dtypes
A      int64
B    float64
C     object
dtype: object

loc bir döngü içinde

Ayrıca locboş oluşturulmuş bir DataFrame eklemek için kullanılan gördük :

df = pd.DataFrame(columns=['A', 'B', 'C'])
for a, b, c in some_function_that_yields_data():
    df.loc[len(df)] = [a, b, c]

Daha önce olduğu gibi, her seferinde ihtiyacınız olan bellek miktarını önceden ayırmadınız, böylece her yeni satır oluşturduğunuzda bellek yeniden büyür . O kadar kötü appendve hatta daha çirkin.

NaN'lerin Boş Veri Çerçevesi

Ve sonra, NaN'lerin bir DataFrame'i ve onunla ilişkili tüm uyarılar var.

df = pd.DataFrame(columns=['A', 'B', 'C'], index=range(5))
df
     A    B    C
0  NaN  NaN  NaN
1  NaN  NaN  NaN
2  NaN  NaN  NaN
3  NaN  NaN  NaN
4  NaN  NaN  NaN

Diğerleri gibi, nesne sütunlarının bir DataFrame'ini oluşturur.

df.dtypes
A    object  # you DON'T want this
B    object
C    object
dtype: object

Eklemek yukarıdaki yöntemler gibi tüm sorunları hala var.

for i, (a, b, c) in enumerate(some_function_that_yields_data()):
    df.iloc[i] = [a, b, c]

Kanıt, puding içerisindedir

Bu yöntemleri zamanlamak, bellekleri ve yardımcı programları açısından ne kadar farklı olduklarını görmenin en hızlı yoludur.

resim açıklamasını buraya girin

Referans için karşılaştırma kodu.


6
Liste
eki

9
Bunun bir milyon kez daha kaldırılması gerekiyor. Asla bir veri çerçevesi büyütmeyin!
Buggy

3
@ user3293236 Eski bir soruya her cevap verdiğinizde alttan başlamanız çok kötü;)
cs95

2
Bu en çok nefret ettiğim şeylerden biri. O kadar çok az oyla bir yerde kalan ve asla kabul edilmeyen 𝒓𝒆𝒂𝒍 𝒄𝒐𝒓𝒓𝒆𝒄𝒕 𝒂𝒏𝒔𝒘𝒆𝒓 görürsünüz. Boş bir panda veri çerçevesi oluşturmak için 𝚍𝚏 = 𝚙𝚍.𝙳𝚊𝚝𝚊𝙵𝚛𝚊𝚖𝚎 ([]) ile kodu özledim. Bu cevabı iptal ediyorum. Mükemmel açıklama, @ cs95!
jonathan

1
Bu tam anlamıyla dokümantasyonda. "Satırları bir DataFrame'e yinelemeli olarak eklemek, tek bir birleştirme işleminden daha fazla hesaplama gerektirebilir. Bu satırları bir listeye eklemek ve ardından listeyi orijinal DataFrame ile bir kerede birleştirmek daha iyi bir çözümdür." pandas.pydata.org/pandas-docs/version/0.21/generated/...
Endolit

132

Sütun adlarıyla boş çerçeveyi başlat

import pandas as pd

col_names =  ['A', 'B', 'C']
my_df  = pd.DataFrame(columns = col_names)
my_df

Bir kareye yeni kayıt ekleme

my_df.loc[len(my_df)] = [2, 4, 5]

Ayrıca bir sözlük iletmek isteyebilirsiniz:

my_dic = {'A':2, 'B':4, 'C':5}
my_df.loc[len(my_df)] = my_dic 

Mevcut çerçevenize başka bir çerçeve ekleyin

col_names =  ['A', 'B', 'C']
my_df2  = pd.DataFrame(columns = col_names)
my_df = my_df.append(my_df2)

Performans hususları

Bir döngünün içine satır ekliyorsanız performans sorunlarını göz önünde bulundurun. Yaklaşık ilk 1000 kayıt için "my_df.loc" performansı daha iyidir, ancak döngüdeki kayıt sayısını artırarak yavaşlar.

Eğer büyük bir döngü içinde (örneğin 10M‌ kayıtları ya da öylesine) ince yapmayı planlıyorsanız, bu iki karışımı kullanarak daha iyi; boyut 1000 civarında olana kadar bir veri çerçevesini iloc ile doldurun, ardından orijinal veri çerçevesine ekleyin ve geçici veri çerçevesini boşaltın. Bu, performansınızı yaklaşık 10 kat artırır.


my_df = my_df.append(my_df2)Ben belirtmedikçe benim için çalışmıyor ignore_index=True.
Nasif Imtiaz Ohi

0

19 satırlı bir veri çerçevesi varsayalım

index=range(0,19)
index

columns=['A']
test = pd.DataFrame(index=index, columns=columns)

A Sütununu sabit tutma

test['A']=10

Sütun b'yi bir döngü tarafından verilen bir değişken olarak tutma

for x in range(0,19):
    test.loc[[x], 'b'] = pd.Series([x], index = [x])

İlk x girişini pd.Series([x], index = [x])herhangi bir değerle değiştirebilirsiniz

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.