[英]split rows by condition in R data.table
我有一個包含3列的數據表,其中一列包含一個鍵:不同長度的值列表。 我希望重新排列表格,使每行只有一個鍵,以值為條件
例如,假設我希望得到值為<= 2的所有行,以便每個鍵都在它自己的行上:\\
input_tbl <-
data.table::data.table(a=c("AA"),b=c("{\"ha:llo\":1,\"wor:ld\":2,\"doog:bye\":3}"),
c=c(1))
那個想要的桌子應該是
tbl_output <- data.table::data.table(a=c("AA",
"AA"),b=c("ha:llo","wor:ld"), c=c(1,1), s=c(1,2))
我曾嘗試過以下功能:
data_table_clean <- function(dt){
dt[ ,"b" := data.table::tstrsplit(b, ',', fixed = T),by=c(a, c)]
dt[,c('b', 's'):= data.table::tstrsplit(b, ':', fixed=TRUE)]
return(dt[s <=2,])
}
這會產生以下錯誤
“eval中的錯誤(expr,envir,enclos):對象'a'未找到”
當然,歡迎任何建議。
密鑰實際上是以下形式:
input2_tbl <-
data.table::data.table(a=c("AA"),b=c("{\"99:1d:3u:7y:89:67\":1,\"99:1D:34:YY:T6:Y6\":2,\"ll:5Y:UY:56:R5:R6\":3}"),
c=c(1))
因此輸出表應該是:
tbl2_output <- data.table::data.table(a=c("AA",
"AA"),b=c(""99:1d:3u:7y:89:67","99:1D:34:YY:T6:Y6"),
c=c(1,1), s=c(1,2))
謝謝!
data_table_clean <- function(dt){
res <- dt[, data.table::tstrsplit(unlist(strsplit(gsub('[{}"]', '', b),',', fixed=TRUE)), ":(?=[^:]+$)", perl=TRUE),
by = .(a, c)][V2 > -100]
data.table::setnames(res, 3:4, c("b", "s"))
res
}
運行時我收到以下錯誤:
.subset(x,j)出錯:無效的下標類型'list'
一種選擇是在最終輸出中提取我們需要的字符。 我們使用str_extract
在“a”,“c”分組后執行此操作。 輸出是一個list
,我們將其unlist
list
,將非數字和數字轉換為兩列,然后使用條件s<3
對行進行子集化。
library(stringr)
library(data.table)
input_tbl[, {
tmp <- unlist(str_extract_all(b, "[A-Za-z]+:[A-Za-z]+|\\d+"))
list(b=tmp[c(TRUE, FALSE)], s=tmp[c(FALSE, TRUE)])
}, by = .(a,c)][s<3]
# a c b s
#1: AA 1 ha:llo 1
#2: AA 1 wor:ld 2
或者如果我們使用strsplit/tstrsplit
,按'a','c'分組,我們用gsub
刪除大括號和引號( [{}]"
),拆分,
( strsplit
), unlist
輸出,然后使用tstrsplit
要拆分:
后跟一個數字。子集部分與上面類似。
res <- input_tbl[, tstrsplit(unlist(strsplit(gsub('[{}"]', '',
b), ',', fixed=TRUE)), ":(?=\\d)", perl=TRUE) ,.(a,c)][V2<3]
setnames(res, 3:4, c("b", "s"))
res
# a c b s
#1: AA 1 ha:llo 1
#2: AA 1 wor:ld 2
對於更新的數據集,我們可以做tstrsplit
上的最后一個分隔符( :
)
res1 <- input2_tbl[, tstrsplit(unlist(strsplit(gsub('[{}"]', '',
b),',', fixed=TRUE)), ":(?=[^:]+$)", perl=TRUE) ,
by = .(a, c)][V2 < 3]
setnames(res1, 3:4, c("b", "s"))
res1
# a c b s
# 1: AA 1 99:1d:3u:7y:89:67 1
# 2: AA 1 99:1D:34:YY:T6:Y6 2
由於您似乎正在使用JSON對象,為什么不使用解析JSON的東西,例如“jsonlite”包?
有了它,你可以創建一個簡單的函數,如下所示:
myFun <- function(invec) {
require(jsonlite)
x <- fromJSON(invec)
list(b = names(x), s = unlist(x))
}
現在,應用於您的數據集,您將獲得:
input_tbl[, myFun(b), by = .(a, c)]
# a c b s
# 1: AA 1 ha:llo 1
# 2: AA 1 wor:ld 2
# 3: AA 1 doog:bye 3
並且,對於子集:
input_tbl[, myFun(b), by = .(a, c)][s <= 2]
# a c b s
# 1: AA 1 ha:llo 1
# 2: AA 1 wor:ld 2
您甚至可以重寫myFun
函數來添加“閾值”參數,該參數允許您在函數本身內進行子集化。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.