Di Pandas, ketika saya memilih label yang hanya memiliki satu entri dalam indeks, saya mendapatkan kembali Seri, tetapi ketika saya memilih entri yang memiliki lebih dari satu entri, saya mendapatkan kembali bingkai data.
Mengapa demikian? Apakah ada cara untuk memastikan saya selalu mendapatkan kembali bingkai data?
In [1]: import pandas as pd
In [2]: df = pd.DataFrame(data=range(5), index=[1, 2, 3, 3, 3])
In [3]: type(df.loc[3])
Out[3]: pandas.core.frame.DataFrame
In [4]: type(df.loc[1])
Out[4]: pandas.core.series.Series
KeyError
ketika saya mencoba.loc[[nonexistent_label]]
..loc
jauh lebih lambat daripada tanpa itu. Agar tetap dapat dibaca tetapi juga lebih cepat, lebih baik digunakandf.loc[1:1]
Anda memiliki indeks dengan tiga item indeks
3
. Untuk alasan inidf.loc[3]
akan mengembalikan dataframe.Alasannya adalah Anda tidak menentukan kolomnya. Jadi
df.loc[3]
pilih tiga item dari semua kolom (yaitu kolom0
), sementaradf.loc[3,0]
akan mengembalikan Seri. Misalnyadf.loc[1:2]
juga mengembalikan dataframe, karena Anda mengiris baris.Memilih satu baris (sebagai
df.loc[1]
) mengembalikan Seri dengan nama kolom sebagai indeks.Jika Anda ingin memastikan selalu memiliki DataFrame, Anda dapat mengiris seperti
df.loc[1:1]
. Pilihan lainnya adalah boolean indexing (df.loc[df.index==1]
) atau metode take (df.take([0])
, tapi lokasi yang digunakan ini bukan label!).sumber
Gunakan
df['columnName']
untuk mendapatkan Seri dandf[['columnName']]
untuk mendapatkan Dataframe.sumber
TLDR
Ketika menggunakan
loc
df.loc[:]
= Dataframedf.loc[int]
= Dataframe jika Anda memiliki lebih dari satu kolom dan Seri jika Anda hanya memiliki 1 kolom dalam dataframedf.loc[:, ["col_name"]]
= Dataframedf.loc[:, "col_name"]
= SeriTidak menggunakan
loc
df["col_name"]
= Seridf[["col_name"]]
= Dataframesumber
Anda menulis di komentar untuk jawaban joris:
Satu baris tidak diubah menjadi Seri.
Ini ADALAH Seri:
No, I don't think so, in fact; see the edit
Model data objek Pandas telah dipilih seperti itu. Alasannya pasti terletak pada fakta bahwa itu memastikan beberapa keuntungan yang saya tidak tahu (saya tidak sepenuhnya memahami kalimat terakhir dari kutipan, mungkin itu alasannya)
.
Edit: Saya tidak setuju dengan saya
DataFrame tidak dapat terdiri dari elemen yang akan menjadi Seri, karena kode berikut memberikan jenis "Seri" yang sama juga untuk baris seperti untuk kolom:
import pandas as pd df = pd.DataFrame(data=[11,12,13], index=[2, 3, 3]) print '-------- df -------------' print df print '\n------- df.loc[2] --------' print df.loc[2] print 'type(df.loc[1]) : ',type(df.loc[2]) print '\n--------- df[0] ----------' print df[0] print 'type(df[0]) : ',type(df[0])
hasil
-------- df ------------- 0 2 11 3 12 3 13 ------- df.loc[2] -------- 0 11 Name: 2, dtype: int64 type(df.loc[1]) : <class 'pandas.core.series.Series'> --------- df[0] ---------- 2 11 3 12 3 13 Name: 0, dtype: int64 type(df[0]) : <class 'pandas.core.series.Series'>
Jadi, tidak masuk akal untuk berpura-pura bahwa DataFrame terdiri dari Seri karena Seri seperti apa yang seharusnya: kolom atau baris? Pertanyaan dan visi bodoh.
.
Lalu apa itu DataFrame?
Pada jawaban versi sebelumnya saya mengajukan pertanyaan ini, mencoba mencari jawaban atas
Why is that?
bagian pertanyaan OP dan interogasi serupasingle rows to get converted into a series - why not a data frame with one row?
di salah satu komentarnya,sedangkan
Is there a way to ensure I always get back a data frame?
bagian tersebut telah dijawab oleh Dan Allan.Kemudian, seperti yang dikatakan oleh dokumen Pandas di atas bahwa struktur data panda paling baik dilihat sebagai wadah data dimensi yang lebih rendah, bagi saya tampaknya pemahaman tentang mengapa dapat ditemukan dalam karakteristik sifat struktur DataFrame.
Namun, saya menyadari bahwa saran yang dikutip ini tidak boleh dianggap sebagai deskripsi yang tepat tentang sifat struktur data Pandas.
Saran ini tidak berarti bahwa DataFrame adalah wadah Seri.
Ini mengungkapkan bahwa representasi mental dari DataFrame sebagai wadah Seri (baik baris atau kolom sesuai dengan opsi yang dipertimbangkan pada satu momen penalaran) adalah cara yang baik untuk mempertimbangkan DataFrames, meskipun sebenarnya tidak benar-benar terjadi. "Baik" artinya visi ini memungkinkan penggunaan DataFrames dengan efisiensi. Itu saja.
.
Lalu apa itu objek DataFrame?
Kelas DataFrame menghasilkan instance yang memiliki struktur tertentu yang berasal dari kelas dasar NDFrame , yang berasal dari kelas dasar PandasContainer yang juga merupakan kelas induk dari kelas Seri .
Perhatikan bahwa ini benar untuk Pandas hingga versi 0.12. Pada versi 0.13 mendatang, Seri juga akan diturunkan dari kelas NDFrame saja.
# with pandas 0.12 from pandas import Series print 'Series :\n',Series print 'Series.__bases__ :\n',Series.__bases__ from pandas import DataFrame print '\nDataFrame :\n',DataFrame print 'DataFrame.__bases__ :\n',DataFrame.__bases__ print '\n-------------------' from pandas.core.generic import NDFrame print '\nNDFrame.__bases__ :\n',NDFrame.__bases__ from pandas.core.generic import PandasContainer print '\nPandasContainer.__bases__ :\n',PandasContainer.__bases__ from pandas.core.base import PandasObject print '\nPandasObject.__bases__ :\n',PandasObject.__bases__ from pandas.core.base import StringMixin print '\nStringMixin.__bases__ :\n',StringMixin.__bases__
hasil
Series : <class 'pandas.core.series.Series'> Series.__bases__ : (<class 'pandas.core.generic.PandasContainer'>, <type 'numpy.ndarray'>) DataFrame : <class 'pandas.core.frame.DataFrame'> DataFrame.__bases__ : (<class 'pandas.core.generic.NDFrame'>,) ------------------- NDFrame.__bases__ : (<class 'pandas.core.generic.PandasContainer'>,) PandasContainer.__bases__ : (<class 'pandas.core.base.PandasObject'>,) PandasObject.__bases__ : (<class 'pandas.core.base.StringMixin'>,) StringMixin.__bases__ : (<type 'object'>,)
Jadi pemahaman saya sekarang adalah contoh DataFrame memiliki metode tertentu yang telah dibuat untuk mengontrol cara data diekstraksi dari baris dan kolom.
Cara kerja metode ekstraksi ini dijelaskan di halaman ini: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing
Kami menemukan di dalamnya metode yang diberikan oleh Dan Allan dan metode lainnya.
Mengapa metode ekstraksi ini dibuat sebagaimana mestinya?
Hal itu tentunya karena mereka dinilai sebagai yang memberikan kemungkinan dan kemudahan yang lebih baik dalam analisis data.
Persis apa yang diungkapkan dalam kalimat ini:
The mengapa dari ekstraksi data dari contoh DataFRame tidak terletak pada struktur, itu terletak pada mengapa struktur ini. Saya kira bahwa struktur dan fungsi struktur data Panda telah dipahat agar sedapat mungkin intuitif secara intelektual, dan untuk memahami detailnya, seseorang harus membaca blog Wes McKinney.
sumber
Jika tujuannya adalah untuk mendapatkan subset dari kumpulan data menggunakan indeks, sebaiknya hindari penggunaan
loc
atauiloc
. Sebagai gantinya Anda harus menggunakan sintaks yang mirip dengan ini:df = pd.DataFrame(data=range(5), index=[1, 2, 3, 3, 3]) result = df[df.index == 3] isinstance(result, pd.DataFrame) # True result = df[df.index == 1] isinstance(result, pd.DataFrame) # True
sumber
Jika Anda juga memilih indeks frame data maka hasilnya bisa berupa DataFrame atau Seri atau bisa Seri atau skalar (nilai tunggal).
Fungsi ini memastikan bahwa Anda selalu mendapatkan daftar dari pilihan Anda (jika df, indeks, dan kolom valid):
def get_list_from_df_column(df, index, column): df_or_series = df.loc[index,[column]] # df.loc[index,column] is also possible and returns a series or a scalar if isinstance(df_or_series, pd.Series): resulting_list = df_or_series.tolist() #get list from series else: resulting_list = df_or_series[column].tolist() # use the column key to get a series from the dataframe return(resulting_list)
sumber