Tips dan trik broadcasting di DataFrames.jl

 – Beragampengetahuan
6 mins read

Tips dan trik broadcasting di DataFrames.jl – Beragampengetahuan

Oleh: Blog Bogumił Kamiński

Repost dari:

Penyiaran, alias . operator, adalah fitur canggih dari Julia yang memungkinkan Anda melakukannya
dengan mudah memvektorisasi fungsi apa pun. Hari ini saya ingin menulis tentang beberapa siaran populer
template dapat digunakan di DataFrames.jl.

Posting ditulis di bawah Julia 1.9.2 dan DataFrames.jl 1.5.0.

Mari kita buat kerangka data dengan beberapa hal acak:

julia> using DataFrames

julia> using Random

julia> df = DataFrame(rand(5, 6), :auto)
5×6 DataFrame
 Row │ x1         x2         x3         x4        x5        x6
     │ Float64    Float64    Float64    Float64   Float64   Float64
─────┼─────────────────────────────────────────────────────────────────
   1 │ 0.364225   0.690894   0.240867   0.720774  0.331573  0.549766
   2 │ 0.225226   0.241412   0.0793279  0.418206  0.775367  0.35275
   3 │ 0.19913    0.0633375  0.767805   0.280096  0.721995  0.917259
   4 │ 0.708132   0.230088   0.702677   0.947402  0.928979  0.66101
   5 │ 0.0267573  0.0122425  0.549734   0.331788  0.32658   0.00476749

Katakanlah kita ingin mendapatkan kerangka data baru true saat nilai disimpan
dalam kotak yang lebih besar 0.5 Dan false jika tidak. Ini mudah.
Kami baru saja mengudara > operator:

julia> df .> 0.5
5×6 DataFrame
 Row │ x1     x2     x3     x4     x5     x6
     │ Bool   Bool   Bool   Bool   Bool   Bool
─────┼──────────────────────────────────────────
   1 │ false   true  false   true  false   true
   2 │ false  false  false  false   true  false
   3 │ false  false   true  false   true   true
   4 │  true  false   true   true   true   true
   5 │ false  false   true  false  false  false

Sekarang misalkan kita ingin mengganti semua nilai lebih besar dari 0.5 dengan 0.5 Dan
menjaga nilai yang lebih rendah tidak berubah. Ini bisa dilakukan dengan ifelse:

julia> ifelse.(df .> 0.5, 0.5, df)
5×6 DataFrame
 Row │ x1         x2         x3         x4        x5        x6
     │ Float64    Float64    Float64    Float64   Float64   Float64
─────┼─────────────────────────────────────────────────────────────────
   1 │ 0.364225   0.5        0.240867   0.5       0.331573  0.5
   2 │ 0.225226   0.241412   0.0793279  0.418206  0.5       0.35275
   3 │ 0.19913    0.0633375  0.5        0.280096  0.5       0.5
   4 │ 0.5        0.230088   0.5        0.5       0.5       0.5
   5 │ 0.0267573  0.0122425  0.5        0.331788  0.32658   0.00476749

Atau dengan clamp:

julia> clamp.(df, -Inf, 0.5)
5×6 DataFrame
 Row │ x1         x2         x3         x4        x5        x6
     │ Float64    Float64    Float64    Float64   Float64   Float64
─────┼─────────────────────────────────────────────────────────────────
   1 │ 0.364225   0.5        0.240867   0.5       0.331573  0.5
   2 │ 0.225226   0.241412   0.0793279  0.418206  0.5       0.35275
   3 │ 0.19913    0.0633375  0.5        0.280096  0.5       0.5
   4 │ 0.5        0.230088   0.5        0.5       0.5       0.5
   5 │ 0.0267573  0.0122425  0.5        0.331788  0.32658   0.00476749

Demikian pula, kita dapat menjepit nilai [0.1, 0.9] Periode:

julia> clamp.(df, 0.1, 0.9)
5×6 DataFrame
 Row │ x1        x2        x3        x4        x5        x6
     │ Float64   Float64   Float64   Float64   Float64   Float64
─────┼────────────────────────────────────────────────────────────
   1 │ 0.364225  0.690894  0.240867  0.720774  0.331573  0.549766
   2 │ 0.225226  0.241412  0.1       0.418206  0.775367  0.35275
   3 │ 0.19913   0.1       0.767805  0.280096  0.721995  0.9
   4 │ 0.708132  0.230088  0.702677  0.9       0.9       0.66101
   5 │ 0.1       0.1       0.549734  0.331788  0.32658   0.1

Yang penting adalah kita tidak perlu mempertahankan tipe elemen dari kolom sumber tetap.
Asumsikan bahwa kita ingin menetapkan nilai lebih besar dari 0.5 TIBA missing:

julia> ifelse.(df .> 0.5, missing, df)
5×6 DataFrame
 Row │ x1               x2               x3               x4              x5              x6
     │ Float64?         Float64?         Float64?         Float64?        Float64?        Float64?
─────┼─────────────────────────────────────────────────────────────────────────────────────────────────────
   1 │       0.364225   missing                0.240867   missing               0.331573  missing
   2 │       0.225226         0.241412         0.0793279        0.418206  missing               0.35275
   3 │       0.19913          0.0633375  missing                0.280096  missing         missing
   4 │ missing                0.230088   missing          missing         missing         missing
   5 │       0.0267573        0.0122425  missing                0.331788        0.32658         0.00476749

Perhatikan bahwa operasi melakukan promosi otomatis jenis elemen kolom.

Sebagai aktivitas terakhir, pertimbangkan untuk mengambil sign(log(x) + 1) pada kerangka data kami:

julia> sign.(log.(df) .+ 1)
5×6 DataFrame
 Row │ x1       x2       x3       x4       x5       x6
     │ Float64  Float64  Float64  Float64  Float64  Float64
─────┼──────────────────────────────────────────────────────
   1 │    -1.0      1.0     -1.0      1.0     -1.0      1.0
   2 │    -1.0     -1.0     -1.0      1.0      1.0     -1.0
   3 │    -1.0     -1.0      1.0     -1.0      1.0      1.0
   4 │     1.0     -1.0      1.0      1.0      1.0      1.0
   5 │    -1.0     -1.0      1.0     -1.0     -1.0     -1.0

Sekali lagi – semuanya mudah dan intuitif. Bingkai data berperilaku seperti matriks di semua operasi.

Saya harap Anda sekarang nyaman membuat kerangka data baru menggunakan broadcast.

Kita dapat beralih ke operasi di tempat pada kerangka data.

Secara umum, menempatkan bingkai data di sisi kanan misi siaran saja sudah cukup
operator untuk memperbaruinya di tempat:

julia> df2 = copy(df)
5×6 DataFrame
 Row │ x1         x2         x3         x4        x5        x6
     │ Float64    Float64    Float64    Float64   Float64   Float64
─────┼─────────────────────────────────────────────────────────────────
   1 │ 0.364225   0.690894   0.240867   0.720774  0.331573  0.549766
   2 │ 0.225226   0.241412   0.0793279  0.418206  0.775367  0.35275
   3 │ 0.19913    0.0633375  0.767805   0.280096  0.721995  0.917259
   4 │ 0.708132   0.230088   0.702677   0.947402  0.928979  0.66101
   5 │ 0.0267573  0.0122425  0.549734   0.331788  0.32658   0.00476749

julia> df3 = df2
5×6 DataFrame
 Row │ x1         x2         x3         x4        x5        x6
     │ Float64    Float64    Float64    Float64   Float64   Float64
─────┼─────────────────────────────────────────────────────────────────
   1 │ 0.364225   0.690894   0.240867   0.720774  0.331573  0.549766
   2 │ 0.225226   0.241412   0.0793279  0.418206  0.775367  0.35275
   3 │ 0.19913    0.0633375  0.767805   0.280096  0.721995  0.917259
   4 │ 0.708132   0.230088   0.702677   0.947402  0.928979  0.66101
   5 │ 0.0267573  0.0122425  0.549734   0.331788  0.32658   0.00476749

julia> df2 .= log.(df)
5×6 DataFrame
 Row │ x1         x2         x3         x4          x5          x6
     │ Float64    Float64    Float64    Float64     Float64     Float64
─────┼─────────────────────────────────────────────────────────────────────
   1 │ -1.00998   -0.369769  -1.42351   -0.32743    -1.10391    -0.598262
   2 │ -1.49065   -1.42125   -2.53417   -0.87178    -0.254419   -1.04199
   3 │ -1.6138    -2.75928   -0.26422   -1.27262    -0.325737   -0.0863653
   4 │ -0.345124  -1.46929   -0.352858  -0.0540319  -0.0736689  -0.413987
   5 │ -3.62095   -4.40285   -0.598321  -1.10326    -1.11908    -5.34594

julia> df2 === df3
true

Perhatikan bahwa dengan pemeriksaan terakhir, saya memastikannya df2 .= log.(df) berada di tempat.
Kami telah memperbarui konten dari df2dan jangan membuat objek baru.

Namun, terkadang hal-hal menjadi lebih rumit. mempertimbangkan df .> 0.5 operasi yang kami lakukan di atas:

julia> df2 .= df .> 0.5
5×6 DataFrame
 Row │ x1       x2       x3       x4       x5       x6
     │ Float64  Float64  Float64  Float64  Float64  Float64
─────┼──────────────────────────────────────────────────────
   1 │     0.0      1.0      0.0      1.0      0.0      1.0
   2 │     0.0      0.0      0.0      0.0      1.0      0.0
   3 │     0.0      0.0      1.0      0.0      1.0      1.0
   4 │     1.0      0.0      1.0      1.0      1.0      1.0
   5 │     0.0      0.0      1.0      0.0      0.0      0.0

Perhatikan bahwa ada perbedaan dari membuat kerangka data baru df .> 0.5.
Masalahnya adalah kolom dari df2 mempertahankan tipe aslinya. Ini yang diharapkan, seperti kita
ingin operasi sepenuhnya di tempat. Namun, terkadang Anda mungkin ingin berubah
jenis elemen kolom saat melakukan siaran. Ini mungkin, bagaimanapun,
maka Anda perlu menggunakan pengindeksan kerangka data dengan khusus ! pemilih baris pensinyalan
Ganti kolom itu diperlukan:

julia> df2[!, :] .= df .> 0.5
5×6 DataFrame
 Row │ x1     x2     x3     x4     x5     x6
     │ Bool   Bool   Bool   Bool   Bool   Bool
─────┼──────────────────────────────────────────
   1 │ false   true  false   true  false   true
   2 │ false  false  false  false   true  false
   3 │ false  false   true  false   true   true
   4 │  true  false   true   true   true   true
   5 │ false  false   true  false  false  false

julia> df3
5×6 DataFrame
 Row │ x1     x2     x3     x4     x5     x6
     │ Bool   Bool   Bool   Bool   Bool   Bool
─────┼──────────────────────────────────────────
   1 │ false   true  false   true  false   true
   2 │ false  false  false  false   true  false
   3 │ false  false   true  false   true   true
   4 │  true  false   true   true   true   true
   5 │ false  false   true  false  false  false

Memang, kami mendapatkan apa yang kami inginkan. Jadi begitu df3 giliran untuk meyakinkan Anda bahwa
semua operasi masih dilakukan pada objek kerangka data yang sama dan df2 Dan df3
masih menunjuk ke sana.

Izinkan saya memberi contoh perbedaan antara in-place dan column-replace
aktivitas sangat penting dan merupakan kejutan umum bagi pengguna baru.
Itu adalah kasus ketika kami ingin memperkenalkan missing nilai-nilai ke dalam kolom awalnya melarang mereka.

julia> df2 = copy(df)
5×6 DataFrame
 Row │ x1         x2         x3         x4        x5        x6
     │ Float64    Float64    Float64    Float64   Float64   Float64
─────┼─────────────────────────────────────────────────────────────────
   1 │ 0.364225   0.690894   0.240867   0.720774  0.331573  0.549766
   2 │ 0.225226   0.241412   0.0793279  0.418206  0.775367  0.35275
   3 │ 0.19913    0.0633375  0.767805   0.280096  0.721995  0.917259
   4 │ 0.708132   0.230088   0.702677   0.947402  0.928979  0.66101
   5 │ 0.0267573  0.0122425  0.549734   0.331788  0.32658   0.00476749

julia> df2 .= ifelse.(df .> 0.5, missing, df)
ERROR: MethodError: Cannot `convert` an object of type Missing to an object of type Float64

julia> df2[!, :] .= ifelse.(df .> 0.5, missing, df)
5×6 DataFrame
 Row │ x1               x2               x3               x4              x5              x6
     │ Float64?         Float64?         Float64?         Float64?        Float64?        Float64?
─────┼─────────────────────────────────────────────────────────────────────────────────────────────────────
   1 │       0.364225   missing                0.240867   missing               0.331573  missing
   2 │       0.225226         0.241412         0.0793279        0.418206  missing               0.35275
   3 │       0.19913          0.0633375  missing                0.280096  missing         missing
   4 │ missing                0.230088   missing          missing         missing         missing
   5 │       0.0267573        0.0122425  missing                0.331788        0.32658         0.00476749

Perhatikan bahwa df2 tidak diperbolehkan pada awalnya missing nilai di kolom manapun. Karena itu
df2 .= ifelse.(df .> 0.5, missing, df) kegagalan. Namun, sebagai gantinya df2 .= melalui df2[!, :] .=
bekerja, karena ! pemilih secara eksplisit membutuhkan penimpaan kolom asli
dengan yang baru, dimungkinkan untuk mengubah tipenya.

Saya harap Anda menemukan contoh-contoh ini berguna dan mereka akan membantu Anda bekerja dengan DataFrames.jl lebih banyak lagi
dengan mudah dan percaya diri.

Sebagai komentar terakhir, izinkan saya menjelaskan alasannya df2 .= ifelse.(df .> 0.5, missing, df) sepenuhnya di tempat
(dan jangan ganti kolom dengan jenis elemen yang sesuai seperti df2[!, :] .=) karena ini adalah pertanyaan populer.
Ada tiga alasan untuk ini:

  • kinerja: operasi yang sepenuhnya di tempat akan lebih cepat dan mengalokasikan lebih sedikit;
  • aman: dalam kode produksi kita mungkin ingin memastikan jenis kolom tidak diubah secara tidak sengaja;
  • konsistensi desain: operasi dirancang untuk berperilaku seperti bermain pada matriks
    (penugasan siaran digunakan dengan matriks yang memungkinkan untuk mengubah jenis elemennya).

Software Terbaru Saat Ini



Aplikasi yang sedang trend saat ini

object oriented programming, programming language, programming adalah, web programming, belajar programming, tournament software, software, software adalah, contoh software, apa itu software, pengertian software, aplikasi, aplikasi penghasil uang, aplikasi bokep, aplikasi video, programming

#Tips #dan #trik #broadcasting #DataFrames.jl

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *