根据现有列的子字符串在 R data.table 中创建列
Create columns in R data.table based on sub-strings of existing column
我正在尝试使用以下 R data.table 从“参考”字段中创建多个列:
library(data.table)
(dt= data.table(Ref = c("R", "STOP", "STOP_TS", "P", "M", "STOP_P_R"),
Qty= c(2,4,6,8,10,12)))
新列应仅基于单个引用(例如“STOP”和“TS”)而不是组合引用(例如“STOP_TS”)。使用“_”标识单个引用后" 分隔符,新列应采用 "Qty" 字段的值,否则应为零。所需的输出应如下所示:
#Desired Output
(desired=data.table(
Ref= c("R", "STOP", "STOP_TS", "P", "M", "STOP_P_R"),
Qty= c(2,4,6,8,10,12),
R = c(2,0,0,0,0,12),
STOP= c (0,4,6,0,0,12),
TS= c(0,0,6,0,0,0),
P= c(0,0,0,8,0,12),
M=c(0,0,0,0,10,0)))
我的方法存在的问题是正则表达式部分在查看“STOP”时错误地匹配了“P”,因为它没有指定匹配完整 'words'。
library(foreach)
library(data.table)
ref<-unlist(unique(dt$Ref)) #extract unique combined ref
ref2<-strsplit(ref, "_") #split ref by using "_"
ref3<-unique(unlist(ref2)) #extract unique single ref (columns to create)
dt2<-foreach(i=1:length(ref3), .combine='cbind')%do%{
eval(parse(text=paste0("tmp<-ifelse( grepl(ref3[i], dt$Ref), dt$Qty,0)")))
data.table(tmp)
}
names(dt2)<-ref3
(dt3=cbind(dt,dt2))
作为一种检查方式,“P”列的总和应为 20(Ref="P" 为 8,Ref="STOP_P_R" 为 12)。
如有任何意见或建议,我将不胜感激。
dl
一个选项是使用 separate_rows
拆分列,然后使用 pivot_wider
将其重塑为宽格式,并使用 bind_cols
绑定原始数据集
library(dplyr)
library(tidyr)
dt %>%
mutate(rn = row_number()) %>%
separate_rows(Ref) %>%
pivot_wider(names_from = Ref, values_from = Qty,
values_fill = list(Qty = 0)) %>%
select(-rn) %>%
bind_cols(dt, .)
# Ref Qty R STOP TS P M
#1: R 2 2 0 0 0 0
#2: STOP 4 0 4 0 0 0
#3: STOP_TS 6 0 6 6 0 0
#4: P 8 0 0 0 8 0
#5: M 10 0 0 0 0 10
#6: STOP_P_R 12 12 12 0 12 0
或使用 data.table
中的 dcast
library(splitstackshape)
library(data.table)
cbind(dt, dcast(cSplit(dt[, rn := seq_len(.N)], 'Ref', '_', "long"),
rn ~ Ref, value.var = 'Qty', fill = 0)[, rn := NULL])
我们可以使用 splitstackshape
中的 cSplit_e
来获取在 "_"
上分隔的每一行的二进制格式数据。然后我们可以用相应的 Qty
值替换所有的 1。
data <- data.frame(splitstackshape::cSplit_e(dt, "Ref", sep = "_",
type = "character", fill = 0))
cols <- grep('Ref_', names(data))
mat <- which(data[cols] == 1, arr.ind = TRUE)
data[cols][mat] <- data$Qty[mat[, 1]]
data
# Ref Qty Ref_M Ref_P Ref_R Ref_STOP Ref_TS
#1 R 2 0 0 2 0 0
#2 STOP 4 0 0 0 4 0
#3 STOP_TS 6 0 0 0 6 6
#4 P 8 0 8 0 0 0
#5 M 10 10 0 0 0 0
#6 STOP_P_R 12 0 12 12 12 0
我正在尝试使用以下 R data.table 从“参考”字段中创建多个列:
library(data.table)
(dt= data.table(Ref = c("R", "STOP", "STOP_TS", "P", "M", "STOP_P_R"),
Qty= c(2,4,6,8,10,12)))
新列应仅基于单个引用(例如“STOP”和“TS”)而不是组合引用(例如“STOP_TS”)。使用“_”标识单个引用后" 分隔符,新列应采用 "Qty" 字段的值,否则应为零。所需的输出应如下所示:
#Desired Output
(desired=data.table(
Ref= c("R", "STOP", "STOP_TS", "P", "M", "STOP_P_R"),
Qty= c(2,4,6,8,10,12),
R = c(2,0,0,0,0,12),
STOP= c (0,4,6,0,0,12),
TS= c(0,0,6,0,0,0),
P= c(0,0,0,8,0,12),
M=c(0,0,0,0,10,0)))
我的方法存在的问题是正则表达式部分在查看“STOP”时错误地匹配了“P”,因为它没有指定匹配完整 'words'。
library(foreach)
library(data.table)
ref<-unlist(unique(dt$Ref)) #extract unique combined ref
ref2<-strsplit(ref, "_") #split ref by using "_"
ref3<-unique(unlist(ref2)) #extract unique single ref (columns to create)
dt2<-foreach(i=1:length(ref3), .combine='cbind')%do%{
eval(parse(text=paste0("tmp<-ifelse( grepl(ref3[i], dt$Ref), dt$Qty,0)")))
data.table(tmp)
}
names(dt2)<-ref3
(dt3=cbind(dt,dt2))
作为一种检查方式,“P”列的总和应为 20(Ref="P" 为 8,Ref="STOP_P_R" 为 12)。
如有任何意见或建议,我将不胜感激。
dl
一个选项是使用 separate_rows
拆分列,然后使用 pivot_wider
将其重塑为宽格式,并使用 bind_cols
library(dplyr)
library(tidyr)
dt %>%
mutate(rn = row_number()) %>%
separate_rows(Ref) %>%
pivot_wider(names_from = Ref, values_from = Qty,
values_fill = list(Qty = 0)) %>%
select(-rn) %>%
bind_cols(dt, .)
# Ref Qty R STOP TS P M
#1: R 2 2 0 0 0 0
#2: STOP 4 0 4 0 0 0
#3: STOP_TS 6 0 6 6 0 0
#4: P 8 0 0 0 8 0
#5: M 10 0 0 0 0 10
#6: STOP_P_R 12 12 12 0 12 0
或使用 data.table
dcast
library(splitstackshape)
library(data.table)
cbind(dt, dcast(cSplit(dt[, rn := seq_len(.N)], 'Ref', '_', "long"),
rn ~ Ref, value.var = 'Qty', fill = 0)[, rn := NULL])
我们可以使用 splitstackshape
中的 cSplit_e
来获取在 "_"
上分隔的每一行的二进制格式数据。然后我们可以用相应的 Qty
值替换所有的 1。
data <- data.frame(splitstackshape::cSplit_e(dt, "Ref", sep = "_",
type = "character", fill = 0))
cols <- grep('Ref_', names(data))
mat <- which(data[cols] == 1, arr.ind = TRUE)
data[cols][mat] <- data$Qty[mat[, 1]]
data
# Ref Qty Ref_M Ref_P Ref_R Ref_STOP Ref_TS
#1 R 2 0 0 2 0 0
#2 STOP 4 0 0 0 4 0
#3 STOP_TS 6 0 0 0 6 6
#4 P 8 0 8 0 0 0
#5 M 10 10 0 0 0 0
#6 STOP_P_R 12 0 12 12 12 0