Saya ingin menulis kode untuk menghitung dan menjumlahkan serangkaian angka positif dan negatif.
Bilangan positif atau negatif (tidak nol).
Saya memiliki kode tertulis dengan for
loop. Apakah ada alternatif kreatif?
Data
R
set.seed(100)
x <- round(rnorm(20, sd = 0.02), 3)
ular sanca
x = [-0.01, 0.003, -0.002, 0.018, 0.002, 0.006, -0.012, 0.014, -0.017, -0.007,
0.002, 0.002, -0.004, 0.015, 0.002, -0.001, -0.008, 0.01, -0.018, 0.046]
loop
R
sign_indicator <- ifelse(x > 0, 1,-1)
number_of_sequence <- rep(NA, 20)
n <- 1
for (i in 2:20) {
if (sign_indicator[i] == sign_indicator[i - 1]) {
n <- n + 1
} else{
n <- 1
}
number_of_sequence[i] <- n
}
number_of_sequence[1] <- 1
#############################
summation <- rep(NA, 20)
for (i in 1:20) {
summation[i] <- sum(x[i:(i + 1 - number_of_sequence[i])])
}
ular sanca
sign_indicator = [1 if i > 0 else -1 for i in X]
number_of_sequence = [1]
N = 1
for i in range(1, len(sign_indicator)):
if sign_indicator[i] == sign_indicator[i - 1]:
N += 1
else:
N = 1
number_of_sequence.append(N)
#############################
summation = []
for i in range(len(X)):
if number_of_sequence[i] == 1:
summation.append(X[i])
else:
summation.append(sum(X[(i + 1 - number_of_sequence[i]):(i + 1)]))
hasil
x n_of_sequence sum
1 -0.010 1 -0.010
2 0.003 1 0.003
3 -0.002 1 -0.002
4 0.018 1 0.018
5 0.002 2 0.020
6 0.006 3 0.026
7 -0.012 1 -0.012
8 0.014 1 0.014
9 -0.017 1 -0.017
10 -0.007 2 -0.024
11 0.002 1 0.002
12 0.002 2 0.004
13 -0.004 1 -0.004
14 0.015 1 0.015
15 0.002 2 0.017
16 -0.001 1 -0.001
17 -0.008 2 -0.009
18 0.010 1 0.010
19 -0.018 1 -0.018
20 0.046 1 0.046
n_of_sequence
tidak identik dengan yang diinginkanAnda dapat menghitung panjang menjalankan setiap tanda menggunakan
rle
daribase
ke dan melakukan sesuatu seperti ini.Mendapatkan
n_of_sequence
Akhirnya, untuk mendapatkan penjumlahan dari urutan,
sumber
Berikut adalah fungsi non-looping sederhana di R:
Jadi kamu bisa melakukan:
Dibuat pada 2020-02-16 oleh paket reprex (v0.3.0)
sumber
Ini adalah
tidyverse
solusi sederhana ...sumber
Sedangkan untuk Python, seseorang akan datang dengan solusi menggunakan panda library. Sementara itu, berikut ini adalah proposal sederhana:
Keluaran:
Jika Anda membutuhkan daftar terpisah, Anda dapat melakukannya
atau, jika iteratornya OK, cukup
(penjelasan di sini )
sumber
Dua solusi malas yang berbeda di Python, menggunakan modul itertools .
Menggunakan itertools.groupby (dan menumpuk)
Menggunakan itertools.accumulate dengan fungsi akumulasi kustom
Itu
initial
Argumen kata kunci ditambahkan dengan Python 3.8. Di versi sebelumnya, Anda bisa menggunakanitertools.chain
untuk menambahkan (0,0) -tuple:Outputnya seperti yang diharapkan:
sumber
Saya merekomendasikan pelari paket R untuk operasi semacam ini. streak_run menghitung terjadinya berturut-turut dari nilai yang sama, dan sum_run menghitung jumlah di jendela yang panjangnya ditentukan oleh
k
argumen.Ini solusinya:
Tolok ukur di bawah ini untuk membandingkan solusi aktual
sumber
df <- data.table(x)
merupakan salinan data lengkap. Selain itu, Anda mencetak data dalam beberapa contoh (yang merupakan salinan lengkap lainnya) sementara tidak pada yang lain.r = runner_streak(x); d = dt_streak(dt) ; all.equal(r, d$sum)
. Hanya memeriksa beberapa bbuttv_streak
memberikan yang samadt_streak
;count_and_sum
memberi sama denganrunner_streak
yang berbeda dari dua sebelumnya.Di R, Anda juga bisa melakukan:
sumber
Melempar jawaban [r] saya di topi, dioptimalkan untuk kecepatan dan bekerja dengan panjang x (tidak seperti penanya yang sulit dikodekan untuk panjang 20):
Dan, untuk membandingkan waktu menjalankan pada komputer kerja saya saat ini (sangat lambat), inilah output microbenchmark saya menggunakan semua solusi R di utas ini. Tidak mengherankan, solusi yang membuat sebagian besar salinan dan konversi cenderung lebih lambat.
-------------- EDIT -------------- Telah ditunjukkan oleh @nicola bahwa solusi saya bukan yang tercepat untuk jangka waktu yang lebih lama dari x - yang harus cukup jelas karena saya terus membuat salinan vektor dengan menggunakan panggilan seperti x <- c (x, y). Saya hanya menciptakan solusi tercepat untuk panjang = 20 dan hanya microbenchmarked serendah yang saya bisa untuk itu.
Untuk membuat perbandingan yang lebih adil, saya mengedit semua versi untuk menghasilkan kode asli dengan cara yang saya percaya akan lebih cepat, tetapi saya menyambut umpan balik tentang itu. Ini kode benchmarking lengkap saya dan hasil untuk sistem saya yang sangat lambat. Saya menyambut umpan balik.
Seperti yang ditunjukkan oleh hasil ini, untuk panjang yang berbeda dari apa yang saya optimalkan, versi saya lambat. Semakin lama x, semakin lambat untuk menjadi sangat lambat pada semua hal di atas 1000. Versi favorit saya adalah Ronak, yang merupakan tercepat kedua di sistem saya. GoGonzo adalah yang tercepat di mesin saya sejauh ini pada panjang yang lebih panjang ini.
sumber
data.table
@ Ronak, milik Anda adalah urutan besarnya lebih lambat untuk ~ 100000.Dalam Python, selain mendefinisikan kelas untuk menyimpan variabel memori, Anda bisa menggunakan closure untuk mencapai hal yang sama.
Catatan ini hanya berfungsi untuk Python 3 (dalam Python 2 saya pikir Anda tidak dapat mengubah variabel penutupan seperti ini). Hal serupa untuk penjumlahan juga.
sumber
Saya pikir loop akan lebih mudah dibaca, tetapi hanya untuk bersenang-senang, inilah solusi dengan Python menggunakan rekursi:
sumber
Inilah pendekatan dasar R lainnya:
sumber
Reduce
sembunyikan satu loop, jadi ini bukan solusi non-looping.Jawaban python sederhana, abaikan 0 case:
Solusi yang sedikit lebih canggih, juga menangani 0 case:
sumber