[英]How to vectorize a for loop in R for a large dataset
我對 R 比較陌生,我有一個關於數據處理的問題。 主要問題是數據集太大,我想寫一個比for循環更快的向量化函數,但我不知道如何。 數據是關於電影和用戶評分的,格式如下(如下)。
1:
5,3,2005-09-06
1,5,2005-05-13
3,4,2005-10-19
2:
2,4,2005-12-26
3,3,2004-05-03
5,3,2005-11-17
1: 和 2: 代表電影,而其他行代表該電影的用戶 ID、用戶評級和評級日期(按從左到右的順序,用逗號分隔)。 我想將數據格式化為邊緣列表,如下所示:
Movie | User
1: | 5
1: | 1
1: | 3
2: | 2
2: | 3
2: | 5
我寫了下面的代碼來執行這個功能。 基本上,對於每一行,它會檢查它是否是電影 ID(包含“:”)或者它是否是用戶數據。 然后它將電影 id 和用戶 id 組合為每個電影和用戶的兩列,然后將其行綁定到一個新的數據幀。 同時,它也只綁定那些給電影評分為 5 分(滿分 5 分)的用戶。
el <- data.frame(matrix(ncol = 2, nrow = 0))
for (i in 1:nrow(data))
{
if (grepl(':', data[i,]))
{
mid <- data[i,]
} else(grepl(',', data[i,]))
{
if(grepl(',5,', data[i,]))
{
uid <- unlist(strsplit(data[i,], ','))[1]
add <- c(mid, uid)
el <- rbind(el, add)
}
}
}
但是,我有大約 1 億個條目,並且 for 循環整夜運行而無法完成。 有沒有辦法加快這個速度? 我讀過向量化,但我不知道如何向量化這個函數。 有什么幫助嗎?
您可以使用一些正則表達式來完成此操作,為此我將使用stringr 包以及 zoo 包中的na.locf 。 (您必須先安裝 stringr 和 zoo)。
首先,我們將設置您的數據,聽起來像是在一列數據框中:
data <- read.table(textConnection("1:
5,3,2005-09-06
1,5,2005-05-13
3,4,2005-10-19
2:
2,4,2005-12-26
3,3,2004-05-03
5,3,2005-11-17
"))
然后,您可以按照以下步驟操作(注釋中的解釋)。
# Pull out the column as a character vector for simplicity
lines <- data[[1]]
library(stringr)
# Figure out which lines represent movie IDs, and extract IDs
movie_ids <- str_match(lines, "(\\d+):")[, 2]
# Fill the last observation carried forward (locf), to find out
# the most recent non-NA value
library(zoo)
movie_ids_filled <- na.locf(movie_ids)
# Extract the user IDs
user_ids <- str_match(lines, "(\\d+),")[, 2]
# For each line that has a user ID, match it to the movie ID
result <- cbind(movie_ids_filled[!is.na(user_ids)],
user_ids[!is.na(user_ids)])
這得到了結果
[,1] [,2]
[1,] "1" "5"
[2,] "1" "1"
[3,] "1" "3"
[4,] "2" "2"
[5,] "2" "3"
[6,] "2" "5"
這段代碼最重要的部分是正則表達式的使用,特別是"(\\\\d+):"
和(\\\\d+),
括號中的捕獲組。 有關將str_match
與正則表達式一起使用的更多信息,請查看本指南。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.