如何使用 data.table 迭代修改变量?
How to modify a variable iteratively using data.table?
我希望有人能帮我弄清楚如何在 data.table
中多次修改一个变量,或者找到一种适用于大数据的类似方法。
我有一个包含字符串的数据集(确切地说是地址,但确切的内容并不重要),例如:
library(data.table)
library(stringr)
# example addresses although you can imagine other types of strings here
addr <- data.table(street = c('1 main street',
'99 madison avenue',
'340 circle court'))
我有另一个数据集,其中包含一列模式,我想在这些字符串(即 addr
数据集中)中搜索模式,并替换为第二个数据集中另一列中保存的其他字符串。例如:
# example of patterns to search for and what I want to replace them with
abbrev <- data.table(full = c('street', 'avenue', 'circle', 'court'),
abbrev = c('st', 'ave', 'cir', 'ct'))
实际的数据集要大得多:数百万个地址和 300 多个缩写我想检查每个地址。
在循环中执行此操作相当简单,但由于大小,我想使用 data.table
并且可能使用 apply
函数来提高此过程的效率.
我正在努力弄清楚如何准确地写这个。我想要如下内容:
# duplicate addresses so we can compare to changes
addr[, orig.street := street]
# function to substitute abbreviations we want
standardize <- function(word, shorter) {
addr[, street := str_replace_all(street,
paste0(" ", word),
paste0(" ", shorter))]
}
# now run function for all abbreviations we want
addr[, street := mapply(FUN = standardize,
word = abbrev$full,
shorter = abbrev$abbrev,
SIMPLIFY = FALSE, USE.NAMES = FALSE)]
当我在 Rstudio 中 运行 返回错误时,“提供了 4 项要分配给列 'street' 的 3 项。RHS 长度必须为 1(单个值都可以)或完全匹配 LHS 长度。如果您希望 'recycle' RHS,请明确使用 rep() 以使您的代码读者清楚地了解此意图。“
然而它确实给了我想要的东西,尽管有错误:
# it breaks but I do get the desired outcome:
street orig.street
1: 1 main st 1 main street
2: 99 madison ave 99 madison avenue
3: 340 cir ct 340 circle court
我觉得一定有一个解决方案我想念,但我还没有想出来。任何帮助将不胜感激。
您可以使用 stri_replace_all_fixed
及其参数 vectorize_all = FALSE
来自库(stringi):
library(data.table)
library(stringi)
addr <- data.table(orig_street = c('1 main street',
'99 madison avenue',
'340 circle court'))
abbrev <- data.table(full = c('street', 'avenue', 'circle', 'court'),
abbrev = c('st', 'ave', 'cir', 'ct'))
addr[, street := stri_replace_all_fixed(orig_street, abbrev$full, abbrev$abbrev, vectorize_all = FALSE)]
> addr
orig_street street
1: 1 main street 1 main st
2: 99 madison avenue 99 madison ave
3: 340 circle court 340 cir ct
另请参阅 并注意 library(stringr)
导入 library(stringi)
。
另一种方法是 Reduce
方法:
addr[, street2 := Reduce(function(txt, i) gsub(paste0("\b", abbrev$full[i], "\b"), abbrev$abbrev[i], txt),
seq_len(nrow(abbrev)), init = street)][]
# street street2
# <char> <char>
# 1: 1 main street 1 main st
# 2: 99 madison avenue 99 madison ave
# 3: 340 circle court 340 cir ct
注:
- 我明确地向
gsub
正则表达式添加了单词边界 (\b
),这样我们就不会无意中替换单词的一部分。我认为我们需要这个而不是 fixed=TRUE
因为 gsub("court", "ct", "courteous", fixed = TRUE)
returns "cteous"
.
- 如果我们尝试
apply
系列(在 abbrev
上),那么我们会看到每个模式的更新值,但不知道(没有额外工作)哪个有变化;此外,如果有可能(一般来说,这里可能没有)多个缩写模式有用,那么我们需要将每个 pattern/replacement 应用于前一个替换的结果 ,*apply
做不到(那么容易)。
- 不幸的是,
Reduce
不容易遍历帧的行,因此我们遍历行索引 (seq_len(nrow(abbrev))
)。
不过,不禁觉得最后一行真的应该是"340 circle ct"
。在这种情况下,如果我们假设缩写位于字符串的末尾,我们可以改用它:
addr[, street3 := Reduce(function(txt, i) gsub(paste0("\b", abbrev$full[i], "\s*$"), abbrev$abbrev[i], txt),
seq_len(nrow(abbrev)), init = street)][]
# street street2 street3
# <char> <char> <char>
# 1: 1 main street 1 main st 1 main st
# 2: 99 madison avenue 99 madison ave 99 madison ave
# 3: 340 circle court 340 cir ct 340 circle ct
我希望有人能帮我弄清楚如何在 data.table
中多次修改一个变量,或者找到一种适用于大数据的类似方法。
我有一个包含字符串的数据集(确切地说是地址,但确切的内容并不重要),例如:
library(data.table)
library(stringr)
# example addresses although you can imagine other types of strings here
addr <- data.table(street = c('1 main street',
'99 madison avenue',
'340 circle court'))
我有另一个数据集,其中包含一列模式,我想在这些字符串(即 addr
数据集中)中搜索模式,并替换为第二个数据集中另一列中保存的其他字符串。例如:
# example of patterns to search for and what I want to replace them with
abbrev <- data.table(full = c('street', 'avenue', 'circle', 'court'),
abbrev = c('st', 'ave', 'cir', 'ct'))
实际的数据集要大得多:数百万个地址和 300 多个缩写我想检查每个地址。
在循环中执行此操作相当简单,但由于大小,我想使用 data.table
并且可能使用 apply
函数来提高此过程的效率.
我正在努力弄清楚如何准确地写这个。我想要如下内容:
# duplicate addresses so we can compare to changes
addr[, orig.street := street]
# function to substitute abbreviations we want
standardize <- function(word, shorter) {
addr[, street := str_replace_all(street,
paste0(" ", word),
paste0(" ", shorter))]
}
# now run function for all abbreviations we want
addr[, street := mapply(FUN = standardize,
word = abbrev$full,
shorter = abbrev$abbrev,
SIMPLIFY = FALSE, USE.NAMES = FALSE)]
当我在 Rstudio 中 运行 返回错误时,“提供了 4 项要分配给列 'street' 的 3 项。RHS 长度必须为 1(单个值都可以)或完全匹配 LHS 长度。如果您希望 'recycle' RHS,请明确使用 rep() 以使您的代码读者清楚地了解此意图。“
然而它确实给了我想要的东西,尽管有错误:
# it breaks but I do get the desired outcome:
street orig.street
1: 1 main st 1 main street
2: 99 madison ave 99 madison avenue
3: 340 cir ct 340 circle court
我觉得一定有一个解决方案我想念,但我还没有想出来。任何帮助将不胜感激。
您可以使用 stri_replace_all_fixed
及其参数 vectorize_all = FALSE
来自库(stringi):
library(data.table)
library(stringi)
addr <- data.table(orig_street = c('1 main street',
'99 madison avenue',
'340 circle court'))
abbrev <- data.table(full = c('street', 'avenue', 'circle', 'court'),
abbrev = c('st', 'ave', 'cir', 'ct'))
addr[, street := stri_replace_all_fixed(orig_street, abbrev$full, abbrev$abbrev, vectorize_all = FALSE)]
> addr
orig_street street
1: 1 main street 1 main st
2: 99 madison avenue 99 madison ave
3: 340 circle court 340 cir ct
另请参阅 library(stringr)
导入 library(stringi)
。
另一种方法是 Reduce
方法:
addr[, street2 := Reduce(function(txt, i) gsub(paste0("\b", abbrev$full[i], "\b"), abbrev$abbrev[i], txt),
seq_len(nrow(abbrev)), init = street)][]
# street street2
# <char> <char>
# 1: 1 main street 1 main st
# 2: 99 madison avenue 99 madison ave
# 3: 340 circle court 340 cir ct
注:
- 我明确地向
gsub
正则表达式添加了单词边界 (\b
),这样我们就不会无意中替换单词的一部分。我认为我们需要这个而不是fixed=TRUE
因为gsub("court", "ct", "courteous", fixed = TRUE)
returns"cteous"
. - 如果我们尝试
apply
系列(在abbrev
上),那么我们会看到每个模式的更新值,但不知道(没有额外工作)哪个有变化;此外,如果有可能(一般来说,这里可能没有)多个缩写模式有用,那么我们需要将每个 pattern/replacement 应用于前一个替换的结果 ,*apply
做不到(那么容易)。 - 不幸的是,
Reduce
不容易遍历帧的行,因此我们遍历行索引 (seq_len(nrow(abbrev))
)。
不过,不禁觉得最后一行真的应该是"340 circle ct"
。在这种情况下,如果我们假设缩写位于字符串的末尾,我们可以改用它:
addr[, street3 := Reduce(function(txt, i) gsub(paste0("\b", abbrev$full[i], "\s*$"), abbrev$abbrev[i], txt),
seq_len(nrow(abbrev)), init = street)][]
# street street2 street3
# <char> <char> <char>
# 1: 1 main street 1 main st 1 main st
# 2: 99 madison avenue 99 madison ave 99 madison ave
# 3: 340 circle court 340 cir ct 340 circle ct