Python pandas: Pertahankan kolom yang dipilih sebagai DataFrame, bukan Seri

92

Saat memilih satu kolom dari DataFrame pandas (katakanlah df.iloc[:, 0],, df['A']atau df.A, dll), vektor yang dihasilkan secara otomatis dikonversi ke Seri, bukan ke DataFrame kolom tunggal. Namun, saya menulis beberapa fungsi yang menggunakan DataFrame sebagai argumen input. Oleh karena itu, saya lebih suka berurusan dengan DataFrame kolom tunggal daripada Seri sehingga fungsinya dapat mengasumsikan bahwa df.columns dapat diakses. Sekarang saya harus secara eksplisit mengubah Seri menjadi DataFrame dengan menggunakan sesuatu seperti pd.DataFrame(df.iloc[:, 0]). Ini sepertinya bukan metode yang paling bersih. Apakah ada cara yang lebih elegan untuk mengindeks dari DataFrame secara langsung sehingga hasilnya adalah DataFrame kolom tunggal dan bukan Seri?


sumber
6
df.iloc [:, [0]] atau df [['A']]; df.A hanya akan memberikan kembali seri namun
Jeff

Jawaban:

99

Seperti yang disebutkan @Jeff, ada beberapa cara untuk melakukan ini, tetapi saya merekomendasikan penggunaan loc / iloc agar lebih eksplisit (dan meningkatkan kesalahan lebih awal jika Anda mencoba sesuatu yang ambigu):

In [10]: df = pd.DataFrame([[1, 2], [3, 4]], columns=['A', 'B'])

In [11]: df
Out[11]:
   A  B
0  1  2
1  3  4

In [12]: df[['A']]

In [13]: df[[0]]

In [14]: df.loc[:, ['A']]

In [15]: df.iloc[:, [0]]

Out[12-15]:  # they all return the same thing:
   A
0  1
1  3

Dua pilihan terakhir menghilangkan ambiguitas dalam kasus nama kolom integer (tepatnya mengapa loc / iloc dibuat). Sebagai contoh:

In [16]: df = pd.DataFrame([[1, 2], [3, 4]], columns=['A', 0])

In [17]: df
Out[17]:
   A  0
0  1  2
1  3  4

In [18]: df[[0]]  # ambiguous
Out[18]:
   A
0  1
1  3
Andy Hayden
sumber
2
Maaf mengganggu Anda, tapi hanya pertanyaan singkat seputar ini. Saya melihat bagaimana ekstra []membuat hasilnya menjadi DataFramea Series, tetapi di mana dalam dokumen pandas apakah sintaks pengindeksan semacam ini dibahas? Saya hanya mencoba mendapatkan nama "resmi" untuk teknik pengindeksan ini sehingga saya benar-benar memahaminya. Terima kasih!
sparc_spread
3
@sparc_spread pandas.pydata.org/pandas-docs/stable/indexing.html#basics "Anda dapat meneruskan daftar kolom ke [] untuk memilih kolom dalam urutan itu." Saya tidak yakin apakah ini memiliki nama!
Andy Hayden
Ya sepertinya tidak ada - tapi saya akan tetap menggunakannya mulai sekarang. Sungguh menakjubkan betapa banyak hal yang terkubur di API dan dokumen. Terima kasih!
sparc_spread
Perbedaan ini berguna bagi saya, karena terkadang saya menginginkan satu kolom DataFrame sehingga saya dapat menggunakan metode DataFrame pada data yang tidak tersedia di Series. (ISTR metode plot berperilaku berbeda). Itu adalah pencerahan bagi saya ketika saya menyadari bahwa saya dapat menggunakan daftar elemen tunggal!
RufusVS
4

Seperti yang direkomendasikan Andy Hayden , menggunakan .iloc / .loc untuk mengindeks kerangka data (kolom tunggal) adalah cara yang tepat; Hal lain yang perlu diperhatikan adalah bagaimana mengekspresikan posisi indeks. Gunakan label / posisi Indeks yang terdaftar sambil menentukan nilai argumen untuk diindeks sebagai Dataframe; kegagalan untuk melakukannya akan mengembalikan 'pandas.core.series.Series'

Memasukkan:

    A_1 = train_data.loc[:,'Fraudster']
    print('A_1 is of type', type(A_1))
    A_2 = train_data.loc[:, ['Fraudster']]
    print('A_2 is of type', type(A_2))
    A_3 = train_data.iloc[:,12]
    print('A_3 is of type', type(A_3))
    A_4 = train_data.iloc[:,[12]]
    print('A_4 is of type', type(A_4))

Keluaran:

    A_1 is of type <class 'pandas.core.series.Series'>
    A_2 is of type <class 'pandas.core.frame.DataFrame'>
    A_3 is of type <class 'pandas.core.series.Series'>
    A_4 is of type <class 'pandas.core.frame.DataFrame'>
Sumanth Lazarus
sumber
1

Anda dapat menggunakan df.iloc[:, 0:1], dalam hal ini vektor yang dihasilkan adalah a DataFramedan bukan seri.

Seperti yang Anda lihat:

masukkan deskripsi gambar di sini

p47hf1nd3r
sumber
1

Ketiga pendekatan ini telah disebutkan:

pd.DataFrame(df.loc[:, 'A'])  # Approach of the original post
df.loc[:,[['A']]              # Approach 2 (note: use iloc for positional indexing)
df[['A']]                     # Approach 3

pd.Series.to_frame () adalah pendekatan lain.

Karena ini adalah metode, ini dapat digunakan dalam situasi di mana pendekatan kedua dan ketiga di atas tidak berlaku. Secara khusus, ini berguna saat menerapkan beberapa metode ke kolom dalam kerangka data Anda dan Anda ingin mengonversi keluaran menjadi kerangka data, bukan rangkaian. Misalnya, dalam Notebook Jupyter, rangkaian tidak akan memiliki keluaran yang bagus, tetapi kerangka data akan.

# Basic use case: 
df['A'].to_frame()

# Use case 2 (this will give you pretty output in a Jupyter Notebook): 
df['A'].describe().to_frame()

# Use case 3: 
df['A'].str.strip().to_frame()

# Use case 4: 
def some_function(num): 
    ...

df['A'].apply(some_function).to_frame()
Null_Vallue_
sumber