あるリストから別のリストの特定のアイテムにアイテムを追加

Adding items from one list to specific items of another list – StackOverflow

まず,ピュアに考える場合.
インデックス操作よりもzipを用いてイテレートする方がリーズナブル.

a = [1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000]
b = [-10, 20, -88, 15, 10, -6, 10, 10]
res = []
for ax, bx in zip(a, b):
  res.append(ax if bx < 0 else res[-1]+bx)
res # [1000, 1020, 3000, 3015, 3025, 6000, 6010, 6020]
[1000, 1020, 3000, 3015, 3025, 6000, 6010, 6020]
a = [1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000]
b = [-10, 20, -88, 15, 10, -6, 10, 10]
a *= 100000
b *= 100000
%%timeit
res = []
for i in range(len(b)):
  res.append(a[i] if b[i] < 0 else res[-1]+b[i])
res
10 loops, best of 3: 156 ms per loop
%%timeit
res = []
for ax, bx in zip(a, b):
  res.append(ax if bx < 0 else res[-1]+bx)
res
10 loops, best of 3: 127 ms per loop

 
 
より高速性を期待する場合,Numpyソリューションを考える.

import numpy as np


def specified_cumsum(a, cond):
  arr = a.copy()
  ind = np.flatnonzero(cond)
  arr[ind[1:]] -= np.add.reduceat(arr, ind)[:-1]
  return arr.cumsum(0)


def func(a, b):
  a = np.asarray(a)
  b = np.asarray(b)
  mask = b < 0
  res = np.where(mask, a, b)
  return specified_cumsum(res, mask)


a = [1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000]
b = [-10, 20, -88, 15, 10, -6, 10, 10]
func(a, b)
array([1000, 1020, 3000, 3015, 3025, 6000, 6010, 6020])
a = [1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000]
b = [-10, 20, -88, 15, 10, -6, 10, 10]
a *= 100000
b *= 100000
%timeit func(a, b)
10 loops, best of 3: 107 ms per loop

データがリストで与えられた場合,変換部分がボトルネックになる.
numpy.ndarrayで与えられた場合,

a = [1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000]
b = [-10, 20, -88, 15, 10, -6, 10, 10]
a *= 100000
b *= 100000
a = np.array(a)
b = np.array(b)
%timeit func(a, b)
10 loops, best of 3: 21.8 ms per loop
a = [1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000]
b = [-10, 20, -88, 15, 10, -6, 10, 10]
a *= 1000000
b *= 1000000
%%timeit
res = []
for ax, bx in zip(a, b):
  res.append(ax if bx < 0 else res[-1]+bx)
res # [1000, 1020, 3000, 3015, 3025, 6000, 6010, 6020]
1 loop, best of 3: 1.19 s per loop
%timeit func(a, b)

a = np.array(a)
b = np.array(b)
%timeit func(a, b)
1 loop, best of 3: 1.04 s per loop
10 loops, best of 3: 175 ms per loop

 
 
関連:
シーケンシャルな値の累積和(cumsum)

カテゴリー: 未分類 パーマリンク

あるリストから別のリストの特定のアイテムにアイテムを追加 への3件のフィードバック

  1. ピンバック: pandas.DataFrame.applyは(時空間効率の観点からは)使用するべきではない – 使用すべき明確な理由がない限りpandas.DataFrame.applyはリーズナブルチョイスになり得ない | 粉末@それは風のように

  2. ピンバック: pandas.DataFrame.applyは(時空間効率の観点からは)使用するべきではない – 使用すべき明確な理由がない限りpandas.DataFrame.applyはリーズナブルチョイスになり得ない | 粉末@それは風のように

  3. ピンバック: データフレームの任意列における条件から降順の累積和を求める | 粉末@それは風のように (日記)

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google フォト

Google アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください