Saya memiliki pandas dataframe
di mana satu kolom string teks berisi nilai yang dipisahkan koma. Saya ingin membagi setiap bidang CSV dan membuat baris baru per entri (asumsikan bahwa CSV bersih dan hanya perlu dibagi pada ','). Misalnya, a
harus menjadi b
:
In [7]: a
Out[7]:
var1 var2
0 a,b,c 1
1 d,e,f 2
In [8]: b
Out[8]:
var1 var2
0 a 1
1 b 1
2 c 1
3 d 2
4 e 2
5 f 2
Sejauh ini, saya telah mencoba berbagai fungsi sederhana, tetapi .apply
metode ini tampaknya hanya menerima satu baris sebagai nilai balik ketika digunakan pada suatu sumbu, dan saya tidak dapat mulai .transform
bekerja. Setiap saran akan sangat dihargai!
Contoh data:
from pandas import DataFrame
import numpy as np
a = DataFrame([{'var1': 'a,b,c', 'var2': 1},
{'var1': 'd,e,f', 'var2': 2}])
b = DataFrame([{'var1': 'a', 'var2': 1},
{'var1': 'b', 'var2': 1},
{'var1': 'c', 'var2': 1},
{'var1': 'd', 'var2': 2},
{'var1': 'e', 'var2': 2},
{'var1': 'f', 'var2': 2}])
Saya tahu ini tidak akan berhasil karena kami kehilangan meta-data DataFrame dengan melewati numpy, tetapi itu akan memberi Anda gambaran tentang apa yang saya coba lakukan:
def fun(row):
letters = row['var1']
letters = letters.split(',')
out = np.array([row] * len(letters))
out['var1'] = letters
a['idx'] = range(a.shape[0])
z = a.groupby('idx')
z.transform(fun)
Jawaban:
Bagaimana dengan sesuatu yang seperti ini:
Maka Anda hanya perlu mengganti nama kolom
sumber
UPDATE2: fungsi vektorisasi yang lebih umum, yang akan berfungsi untuk banyak
normal
dan beberapalist
kolomDemo:
Beberapa
list
kolom - semualist
kolom harus memiliki # elemen yang sama di setiap baris:mempertahankan nilai indeks asli:
Mempersiapkan:
Kolom CSV:
menggunakan trik kecil ini kita dapat mengonversi kolom mirip CSV ke
list
kolom:UPDATE: pendekatan umum vektor (akan bekerja juga untuk banyak kolom):
DF asli:
Larutan:
pertama mari kita mengonversi string CSV ke daftar:
Sekarang kita bisa melakukan ini:
Jawaban LAMA:
Terinspirasi oleh solusi @AFinkelstein , saya ingin membuatnya sedikit lebih umum yang dapat diterapkan pada DF dengan lebih dari dua kolom dan secepat, juga hampir, secepat solusi AFinkelstein):
sumber
.explode()
metode ke API (juga lihat jawaban ini ).Setelah percobaan yang menyakitkan untuk menemukan sesuatu yang lebih cepat daripada jawaban yang diterima, saya berhasil. Itu berlari sekitar 100x lebih cepat pada dataset saya mencobanya.
Jika seseorang tahu cara membuat ini lebih elegan, silakan modifikasi kode saya. Saya tidak dapat menemukan cara yang berfungsi tanpa mengatur kolom lain yang ingin Anda simpan sebagai indeks dan kemudian mengatur ulang indeks dan penamaan ulang kolom, tetapi saya membayangkan ada hal lain yang berfungsi.
sumber
TypeError: object of type 'float' has no len()
pada langkah pertama (DataFrame(df.var1.str.split(',').tolist())
)NaN
di kolom itu, jadi penggantinyab = DataFrame(a.var1.str.split(',').values.tolist(), index=a.var2).stack()
Inilah fungsi yang saya tulis untuk tugas umum ini. Ini lebih efisien daripada metode
Series
/stack
. Urutan kolom dan nama dipertahankan.Dengan fungsi ini, pertanyaan aslinya semudah:
sumber
Panda> = 0,25
Metode Series dan DataFrame menentukan
.explode()
metode yang meledakkan daftar menjadi baris terpisah. Lihat bagian dokumen pada Meledak kolom seperti daftar .Karena Anda memiliki daftar string yang dipisahkan koma, pisahkan string pada koma untuk mendapatkan daftar elemen, lalu panggil
explode
kolom itu.Perhatikan bahwa
explode
hanya berfungsi pada satu kolom (untuk saat ini).NaNs dan daftar kosong mendapatkan perawatan yang layak tanpa Anda harus melompat melalui lingkaran untuk melakukannya dengan benar.
Ini adalah keuntungan serius dari solusi berbasis
ravel
+repeat
(yang mengabaikan daftar kosong sepenuhnya, dan tersedak NaNs).sumber
Pertanyaan serupa sebagai: panda: Bagaimana cara membagi teks dalam kolom menjadi beberapa baris?
Anda bisa melakukannya:
sumber
s.name = 'var1'
TL; DR
Demonstrasi
Mari kita membuat kerangka data baru
d
yang memiliki daftarKomentar umum
Saya akan gunakan
np.arange
denganrepeat
untuk menghasilkan posisi indeks dataframe yang dapat saya gunakan denganiloc
.Faq
Kenapa saya tidak menggunakan
loc
?Karena indeks mungkin tidak unik dan menggunakan
loc
akan mengembalikan setiap baris yang cocok dengan indeks yang diminta.Mengapa Anda tidak menggunakan
values
atribut dan mengirisnya?Saat memanggil
values
, jika keseluruhan kerangka data berada dalam satu "blok" yang kohesif, Pandas akan mengembalikan tampilan array yang merupakan "blok". Kalau tidak, Panda harus merakit array baru. Ketika berbatu, array itu harus dari tipe yang seragam. Seringkali itu berarti mengembalikan array dengan dtypeobject
. Dengan menggunakaniloc
alih-alih mengirisvalues
atribut, saya mengurangi diri saya karena harus berurusan dengan itu.Kenapa kamu menggunakan
assign
?Saat saya gunakan
assign
menggunakan nama kolom yang sama dengan yang saya meledak, saya menimpa kolom yang ada dan mempertahankan posisinya dalam kerangka data.Mengapa nilai indeks diulang?
Berdasarkan penggunaan
iloc
pada posisi berulang, indeks yang dihasilkan menunjukkan pola berulang yang sama. Satu pengulangan untuk setiap elemen daftar atau string.Ini dapat diatur ulang dengan
reset_index(drop=True)
Untuk Strings
Saya tidak ingin harus membagi string sebelum waktunya. Jadi alih-alih saya menghitung kemunculan
sep
argumen tersebut dengan asumsi bahwa jika saya harus membelah, panjang daftar yang dihasilkan akan menjadi satu lebih dari jumlah pemisah.Saya kemudian menggunakannya
sep
untukjoin
string itusplit
.Untuk daftar
Mirip dengan string kecuali saya tidak perlu menghitung kemunculannya
sep
karena sudah terpecah.Saya menggunakan Numpy
concatenate
untuk menyatukan daftar.sumber
Ada kemungkinan untuk membagi dan meledak dataframe tanpa mengubah struktur dataframe
Memasukkan:
Di luar:
Edit-1
Mengindeks ulang berdasarkan kolom referensi dan menyelaraskan informasi nilai kolom dengan tumpukan
Di luar:
sumber
Saya datang dengan solusi untuk kerangka data dengan jumlah kolom yang berubah-ubah (sementara masih hanya memisahkan entri satu kolom pada satu waktu).
sumber
Berikut adalah pesan yang cukup mudah yang menggunakan
split
metode dari pandastr
accessor dan kemudian menggunakan NumPy untuk meratakan setiap baris menjadi satu array.Nilai-nilai yang sesuai diambil dengan mengulangi kolom yang tidak terbagi dengan jumlah kali yang benar
np.repeat
.sumber
Saya telah berjuang dengan pengalaman di luar memori menggunakan berbagai cara untuk meledakkan daftar saya jadi saya menyiapkan beberapa tolok ukur untuk membantu saya memutuskan jawaban mana yang akan dihapus. Saya menguji lima skenario dengan proporsi panjang daftar yang berbeda-beda terhadap jumlah daftar. Bagikan hasil di bawah ini:
Waktu: (lebih sedikit lebih baik, klik untuk melihat versi besar)
Penggunaan memori puncak: (lebih sedikit lebih baik)
Kesimpulan :
Detail lengkap (fungsi dan kode pembandingan) ada di inti GitHub ini . Harap dicatat bahwa masalah tolok ukur disederhanakan dan tidak termasuk pemisahan string ke dalam daftar - yang sebagian besar solusi dilakukan dengan cara yang sama.
sumber
Berdasarkan solusi @ DMulligan yang sangat baik , berikut adalah fungsi generik yang di-vectorized (tanpa loop) yang membagi kolom dari dataframe menjadi beberapa baris, dan menggabungkannya kembali ke dataframe asli. Ini juga menggunakan
change_column_order
fungsi generik yang hebat dari jawaban ini .Contoh:
Perhatikan bahwa ini mempertahankan indeks dan urutan kolom asli. Ini juga bekerja dengan kerangka data yang memiliki indeks non-sekuensial.
sumber
Pemecahan fungsi string dapat mengambil opsi boolean argumen 'perluas'.
Berikut ini solusi menggunakan argumen ini:
sumber
Hanya menggunakan jawaban jiln yang sangat baik dari atas, tetapi perlu diperluas untuk membagi beberapa kolom. Kupikir aku akan berbagi.
sumber
meningkatkan jawaban MaxU dengan dukungan MultiIndex
sumber
One-liner using
split(___, expand=True)
danlevel
danname
argumen untukreset_index()
:Jika Anda perlu
b
terlihat persis seperti dalam pertanyaan, Anda juga dapat melakukan:sumber
Saya datang dengan solusi berikut untuk masalah ini:
sumber
Solusi lain yang menggunakan paket salinan python
sumber
Ada banyak jawaban di sini tapi saya terkejut tidak ada yang menyebutkan fungsi meledak dalam panda. Lihat tautan di bawah ini: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.explode.html#pandas.DataFrame.explode
Untuk beberapa alasan saya tidak dapat mengakses fungsi itu, jadi saya menggunakan kode di bawah ini:
Di atas adalah contoh data saya. Seperti yang Anda lihat orang kolom memiliki serangkaian orang, dan saya mencoba untuk meledakkannya. Kode yang saya berikan berfungsi untuk data tipe daftar. Jadi cobalah untuk memasukkan data teks yang dipisahkan koma ke dalam format daftar. Juga karena kode saya menggunakan fungsi bawaan, ini jauh lebih cepat daripada fungsi kustom / terapkan.
Catatan: Anda mungkin perlu menginstal pandas_explode dengan pip.
sumber
Saya memiliki masalah yang sama, solusi saya adalah mengkonversi dataframe ke daftar kamus terlebih dahulu, kemudian melakukan transisi. Inilah fungsinya:
Contoh:
Anda juga dapat mengubah fungsi sedikit untuk mendukung memisahkan baris jenis daftar.
sumber