主頁 > 移動端開發 > 對改變矩陣列的for回圈進行矢量化

對改變矩陣列的for回圈進行矢量化

2022-06-16 12:30:34 移動端開發

假設我有一個包含 100 棵樹的向量。然后我將這些樹齡分別為 5 年、10 年、15 年和 20 年,以創建今年的樹齡矩陣和未來的四個 5 年規劃期。

但是后來,我決定砍掉其中一些樹(每個計劃期間只有 10 棵),記錄在 T/F 值矩陣中,其中 T 被收獲而 F 不是(樹木不能被收獲兩次)。

age.vec <- sample(x = 1:150, size = 100, replace = T) # create our trees
age.mat <- cbind(age.vec, age.vec 5, age.vec   10, age.vec   15, age.vec   20) # grow them up
x.mat <- matrix(data = F, nrow = 100, ncol = 5) # create the empty harvest matrix
x.mat[cbind(sample(1:100, size = 50), rep(1:5, each = 10))] <-  T # 10 trees/year harvested

那么,當年采伐的樹齡為零: age.mat[x.mat] <- 0

然后,我想在接下來的時間里再次老化收獲的樹木。例如,如果在第一個計劃期收獲一棵樹,在第二個計劃期(5 年后),我希望樹的年齡為 5,然后在第三個計劃期(10 年后),我希望樹齡樹的長度為 10。我已在以下 for 回圈中成功實作了這一點:

for (i in 2:5){ # we don't need to calculate over the first year
  age.mat[,i]<-age.mat[,i-1] 5L # add 5 to previous year
  age.mat[x.mat[,i],i] <- 0L # reset age of harvested trees to zero
}

這可行,但是,它笨重且緩慢。有沒有辦法更快地實作這個(即沒有for回圈)?它也是在一個函式中實作的,這意味著使用“apply”實際上會減慢速度,因此需要直接對其進行矢量化。這是我要迭代數千次的東西,所以速度至關重要!

謝謝!

uj5u.com熱心網友回復:

根據rbenchmark.

這是一種依賴于這樣一個事實的方法,即采伐一棵樹不會停止時間的流逝,它只是重置時鐘。因此,我們可以將收獲視為從所有未來年齡中減去收獲年齡。

x.die <- x.mat * age.mat 
x.dif <- t(apply(x.die, 1, cumsum))
age.mat2 <- age.mat - x.dif

x.die,通過將收成乘以年齡,我們得到每次收成的年齡。下一行計算每一行的這些累積和,最后我們從原始年齡中減去這些。

我假設您的“樹木不能收獲兩次”意味著我們永遠不會在一行中看到兩個 TRUE x.mat如果每個樹的位置不止一次收獲,我的代碼將無法正常作業。

uj5u.com熱心網友回復:

@Jon Spring 的答案的替代方案t(applymatrixStats::rowCumsums.

library(matrixStats)

n <- 1e4L
n10 <- n/10L
age.mat <- outer(sample(150, n, TRUE), seq(0, 20, 5), " ")
x.mat <- matrix(FALSE, n, 5) # create the empty harvest matrix
# sample harvests so that no tree is harvested twice
x.mat[matrix(c(sample(n, n/2L), sample(n10:(6L*n10 - 1L)) %/% n10), n/2L)] <- TRUE

f1 <- function(age, x) {
  age[x[,1],] <- 0
  for (i in 2:5){ # we don't need to calculate over the first year
    age[,i] <- age[,i - 1]   5L # add 5 to previous year
    age[x[,i], i] <- 0L # reset age of harvested trees to zero
  }
  age
}

f2 <- function(age, x) {
  age - rowCumsums(x*age)
}

microbenchmark::microbenchmark(f1 = f1(age.mat, x.mat),
                               f2 = f2(age.mat, x.mat),
                               check = "equal")
#> Unit: microseconds
#>  expr   min    lq     mean median     uq     max neval
#>    f1 294.4 530.2 1023.450  566.6 629.35 33222.8   100
#>    f2 135.2 263.6  334.622  284.2 307.15  4343.6   100

uj5u.com熱心網友回復:

您可以使用 apply 逐行處理每個向量,然后在函式中使用一些邏輯來調整值。

應該快 4 倍左右

  age.mat |> 
  apply(1, \(x) { 
    
    if(any(x == 0 & (which(x == 0) != length(x)))) { 
      
   x[which(x == 0):length(x)] <- (0:(length(x) - which(x == 0))) * 5
   
   x
    
      } else x
  }) |> t()
     [,1] [,2] [,3] [,4] [,5]
  [1,]  101    0    5   10   15
  [2,]   55   60   65   70   75
  [3,]   23   28   33    0    5
  [4,]    0    5   10   15   20
  [5,]   23   28   33    0    5
  [6,]   84    0    5   10   15
  [7,]   52   57   62    0    5
  [8,]   26   31   36   41    0
  [9,]  114  119  124  129    0
 [10,]   33   38   43   48   53
 [11,]  144  149  154  159  164
 [12,]   19   24   29   34   39
 [13,]   43   48   53   58   63
 [14,]   69   74   79   84   89
 [15,]   98  103  108  113  118
 [16,]  110  115  120  125  130
 [17,]    8   13   18   23   28
 [18,]   16   21   26   31   36
 [19,]    1    6   11   16   21
 [20,]   60   65    0    5   10

uj5u.com熱心網友回復:

我找到了一種方法!我實作了從@john-spring 倒退的想法,在那里我創建了一個矩陣,其中填寫了收獲年份和隨后所有年份的展臺年齡,然后從我預先制作的老化中減去矩陣。我構建了一個類似于 tidyr 中的“fill”或 zoo 中的“na.locf”所做的功能(因為它們太慢了)。

首先,我使用 arrayInd 來確定更改的樹矩陣中的位置。然后我用它來制作另一個矩陣,該矩陣組合每個索引行的重復次數等于周期數減去收獲樹的周期加一,以及一個與周期相同長度的序列向量索引號的周期數。

x.ind <- arrayInd(which(x.mat), dim(x.mat)) # gets index of row that was changed
x.new.ind <- cbind(rep(x.ind[,1], times = nper-x.ind[,2] 1), sequence(nvec = nper-x.ind[,2] 1, from = x.ind[,2]))

例如,如果在位置 [4, 2] 收獲了一棵樹,這意味著第四棵樹是在第二個時期收獲的,并且我們總共有 5 個時期,它將創建一個矩陣:

    [,1] [,2] 
[1,]  4    2
[2,]  4    3
[3,]  4    4
[4,]  4    5

然后我制作了一個向量,其中包含在正確位置收獲的樹木的年齡,其余位置為零(例如,對于我們的示例,如果收獲的樹有 100 年歷史,我們將有一個向量0 0 0 100 0(如果我們有 5 棵樹))。

ages.vec <- vector(mode = "integer", length = nrow(age.mat))
ages.vec[x.ind[,1]]<- age.mat[x.ind]

然后我將這個向量乘以一個邏輯矩陣,上面矩陣中的行、列位置為“T”。

繼續上面的例子,我們得到:

    [,1] [,2] [,3] [,4] [,5]
[1,]  0    0    0    0    0
[2,]  0    0    0    0    0
[3,]  0    0    0    0    0
[4,]  0  100  100  100  100
[5,]  0    0    0    0    0

然后我從我們當前(已經老化)的年齡矩陣中減去它。所以樹四曾經是95 100 105 110 115,現在是95 0 5 10 15

new.ages.mat<- age.mat - replace(x.mat, x.new.ind, TRUE)*ages.vec

雖然這可能不是最優雅的解決方案,但使用 microbenchmark,它比我們的 for 回圈快 90 倍,比 John 創建的可愛的 apply 函式快 3 倍。我會放入微基準呼叫和結果,但是這篇文章已經足夠長了!我知道有更好的方法來創建ages.vec 并將其合并,我將繼續努力,并將用我的結果更新這個答案!

uj5u.com熱心網友回復:

這種方法建立在which使用與 arr.ind=TRUE 一起創建一個兩列矩陣的基礎上,該矩陣對新植樹的起始位置(在第一列中)和時間(在第二列中)進行編碼。它確實違反了函式式編程范式,因為它使用<<-“就地”為age.mat`分配新值。

fiveseq <- seq(0,20, by=5) # this way one only needs to call `seq` once
apply(which(x.mat, arr.ind=TRUE) , 1, 
          function(r) {age.mat[ r[1], r[2]:5] <<- fiveseq[  1:(6-r[2])] } )

總之,它找到新的位置和間隔,并用序列中正確數量的專案替換該行的其余部分{0, 5, 10, 15, 20}

(我很想看看這與您已經建立的基準測驗框架相比如何。)

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/491643.html

標籤:r 表现 循环 for循环 矩阵

上一篇:使用函式庫,成員函式呼叫性能變慢

下一篇:為快速加載檔案格式注冊寬度和決議

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more