通过部分匹配 (R) 连接不同数量的列
Concatenate varying number of columns by partial match (R)
关于 SO 的第一个问题,虽然我已经潜伏了一段时间!我尝试尽职调查并接近答案。
我有一个 300 列的数据框,我想根据匹配的变量名称模式将其合并为大约 10 列。原始数据输出为我提供了一个列,其中包含主要变量名称(在示例中为 "before" 和 "after")和一个数字。在我的 "real" 数据中,每个变量大约有 30 个副本。
我想合并名称中包含 "before" 或 "after," 等的每一列。
我使用 data.table 的语法为这种类型的 "calculated" 列成功创建了变量 "new"。
myTable2[, new := paste(before1, before2, sep = "")]
> myTable2
herenow before1 before2 before3 after1 after2 after3 new
1: 0.3399679 if and where not here blank ifand
2: 0.8181909 for in by through blank blank forin
3: 0.2237681 and where mine yours ours andwhere
4: 0.6161998 and where ha hey hon andwhere
5: 0.7606252 fifth eighth and where not beet fiftheighth
6: 0.5525105 and where not fill are andwhere
但是如您所见,这明确说明了我要合并的列。我想灵活组合,这样如果我有一个变量的 31 个副本和另一个变量的 86 个副本,我不需要 a) 必须知道那个或 b) 必须输入那个。我只想根据基本变量名称(例如 "before")进行匹配并合并列。
我尝试使用 grep 进入下一个级别...
> newvar2 <- paste(grep("before", colnames(myTable2), value = TRUE), collapse = "")
> newvar2
[1] "before1before2before3"
这让我确信我可以将可变数量的值与 grep 模式匹配相结合。
下一步:如何结合这两个步骤,使
new := paste(etc....)
将 grep 步骤作为其参数并组合名称与模式匹配的所有 列 ?
这就是我想要的:
herenow before_Final after_Final
1: 0.339967856 ifandwhere nothereblank
2: 0.818190875 forinby throughblankblank
3: 0.223768051 andwhere mineyoursours
4: 0.616199835 andwhere haheyhon
5: 0.760625218 fiftheighthand wherenotbeet
6: 0.552510532 andwherenot fillare
我正在努力学习更多关于矢量化的知识,但如果我什至可以列出我想要组合的变量类型(例如之前、之后、之间),然后 运行 通过这些,可能在一个循环,那就太好了!所以像
finalVarNames <- c("Before_final", "After_final", "Between_final")
whatToMatch <- c("before", "after", "between")
(此处为循环...)
myTable2[, finalVarNames[i] := paste(grep(whatToMatch[i], myTable2, value = TRUE), collapse = "")]
我知道语法不正确,可能在值参数之前的第二个 "myTable2" 引用中。此代码确实成功创建了新变量,但它是空白的。如何将连接的 grep 匹配变量组放入其中?
感谢您的帮助!
您可以使用 Reduce
函数将选定的列粘贴在一起,方法是在 .SD
语法中通过 grep
指定列。这是使用 data.table
包获取结果的示例:
library(stringi); library(data.table)
myTable2[, paste(stri_trans_totitle(whatToMatch), "final", sep = "_") :=
lapply(whatToMatch, function(wtm) Reduce(function(x,y) paste(x, y, sep = ""),
.SD[, grep(wtm, names(myTable2)), with = F]))]
myTable2
# herenow before1 before2 before3 after1 after2 after3 Before_final After_final
# 1: 0.3399679 if and where not here blank ifandwhere nothereblank
# 2: 0.8181909 for in by through blank blank forinby throughblankblank
# 3: 0.2237681 and where mine yours ours andwhere mineyoursours
# 4: 0.6161998 and where ha hey hon andwhere haheyhon
# 5: 0.7606252 fifth eighth and where not beet fiftheighthand wherenotbeet
# 6: 0.5525105 and where not fill are andwherenot filler
do.call
和Reduce
的一些基准:
dim(myTable2)
# [1] 1572864 9
reduce <- function() myTable2[, paste(stri_trans_totitle(whatToMatch[1:2]), "final", sep = "_") := lapply(whatToMatch[1:2], function(wtm) Reduce(function(x,y) paste(x, y, sep = ""), .SD[, grep(wtm, names(myTable2)), with = F]))]
docall <- function() myTable2[, paste(stri_trans_totitle(whatToMatch[1:2]), "final", sep = "_") := lapply(whatToMatch[1:2], function(wtm) do.call(paste, c(sep = "", .SD[, grep(wtm, names(myTable2)), with = F])))]
microbenchmark::microbenchmark(docall(), reduce(), times = 10)
# Unit: milliseconds
# expr min lq mean median uq max neval
# docall() 707.7818 722.6037 767.8923 737.6272 852.4909 868.8202 10
# reduce() 999.4925 1009.5146 1026.6200 1020.4637 1046.7073 1067.7479 10
关于 SO 的第一个问题,虽然我已经潜伏了一段时间!我尝试尽职调查并接近答案。
我有一个 300 列的数据框,我想根据匹配的变量名称模式将其合并为大约 10 列。原始数据输出为我提供了一个列,其中包含主要变量名称(在示例中为 "before" 和 "after")和一个数字。在我的 "real" 数据中,每个变量大约有 30 个副本。
我想合并名称中包含 "before" 或 "after," 等的每一列。 我使用 data.table 的语法为这种类型的 "calculated" 列成功创建了变量 "new"。
myTable2[, new := paste(before1, before2, sep = "")]
> myTable2
herenow before1 before2 before3 after1 after2 after3 new
1: 0.3399679 if and where not here blank ifand
2: 0.8181909 for in by through blank blank forin
3: 0.2237681 and where mine yours ours andwhere
4: 0.6161998 and where ha hey hon andwhere
5: 0.7606252 fifth eighth and where not beet fiftheighth
6: 0.5525105 and where not fill are andwhere
但是如您所见,这明确说明了我要合并的列。我想灵活组合,这样如果我有一个变量的 31 个副本和另一个变量的 86 个副本,我不需要 a) 必须知道那个或 b) 必须输入那个。我只想根据基本变量名称(例如 "before")进行匹配并合并列。
我尝试使用 grep 进入下一个级别...
> newvar2 <- paste(grep("before", colnames(myTable2), value = TRUE), collapse = "")
> newvar2
[1] "before1before2before3"
这让我确信我可以将可变数量的值与 grep 模式匹配相结合。
下一步:如何结合这两个步骤,使
new := paste(etc....)
将 grep 步骤作为其参数并组合名称与模式匹配的所有 列 ? 这就是我想要的:
herenow before_Final after_Final
1: 0.339967856 ifandwhere nothereblank
2: 0.818190875 forinby throughblankblank
3: 0.223768051 andwhere mineyoursours
4: 0.616199835 andwhere haheyhon
5: 0.760625218 fiftheighthand wherenotbeet
6: 0.552510532 andwherenot fillare
我正在努力学习更多关于矢量化的知识,但如果我什至可以列出我想要组合的变量类型(例如之前、之后、之间),然后 运行 通过这些,可能在一个循环,那就太好了!所以像
finalVarNames <- c("Before_final", "After_final", "Between_final")
whatToMatch <- c("before", "after", "between")
(此处为循环...)
myTable2[, finalVarNames[i] := paste(grep(whatToMatch[i], myTable2, value = TRUE), collapse = "")]
我知道语法不正确,可能在值参数之前的第二个 "myTable2" 引用中。此代码确实成功创建了新变量,但它是空白的。如何将连接的 grep 匹配变量组放入其中?
感谢您的帮助!
您可以使用 Reduce
函数将选定的列粘贴在一起,方法是在 .SD
语法中通过 grep
指定列。这是使用 data.table
包获取结果的示例:
library(stringi); library(data.table)
myTable2[, paste(stri_trans_totitle(whatToMatch), "final", sep = "_") :=
lapply(whatToMatch, function(wtm) Reduce(function(x,y) paste(x, y, sep = ""),
.SD[, grep(wtm, names(myTable2)), with = F]))]
myTable2
# herenow before1 before2 before3 after1 after2 after3 Before_final After_final
# 1: 0.3399679 if and where not here blank ifandwhere nothereblank
# 2: 0.8181909 for in by through blank blank forinby throughblankblank
# 3: 0.2237681 and where mine yours ours andwhere mineyoursours
# 4: 0.6161998 and where ha hey hon andwhere haheyhon
# 5: 0.7606252 fifth eighth and where not beet fiftheighthand wherenotbeet
# 6: 0.5525105 and where not fill are andwherenot filler
do.call
和Reduce
的一些基准:
dim(myTable2)
# [1] 1572864 9
reduce <- function() myTable2[, paste(stri_trans_totitle(whatToMatch[1:2]), "final", sep = "_") := lapply(whatToMatch[1:2], function(wtm) Reduce(function(x,y) paste(x, y, sep = ""), .SD[, grep(wtm, names(myTable2)), with = F]))]
docall <- function() myTable2[, paste(stri_trans_totitle(whatToMatch[1:2]), "final", sep = "_") := lapply(whatToMatch[1:2], function(wtm) do.call(paste, c(sep = "", .SD[, grep(wtm, names(myTable2)), with = F])))]
microbenchmark::microbenchmark(docall(), reduce(), times = 10)
# Unit: milliseconds
# expr min lq mean median uq max neval
# docall() 707.7818 722.6037 767.8923 737.6272 852.4909 868.8202 10
# reduce() 999.4925 1009.5146 1026.6200 1020.4637 1046.7073 1067.7479 10