R data.table 使用 tstrsplit 分解列
R data.table explode column using tstrsplit
我以下面的data.table
为例
df = data.table(id = c(1, 2, 3), val=c("['hello', 'world']", "['hi']", "['so', 'there']"))
我想将类似对象的列表拆分为单独的行,并重复 id
。所以我想要的预期data.table
是下面的
df2 = data.table(id = c(1, 1, 2, 3, 3), val=c("hello", "world", "hi", "so", "there"))
我尝试了以下方法
df[, c("test") := tstrsplit(val, ",", fixed=TRUE)]
但是,我得到了以下错误
Error in [.data.table
(df, , :=
(c("test"), tstrsplit(val, ",",
fixed = TRUE))) : Supplied 2 items to be assigned to 3 items of
column 'test'. If you wish to 'recycle' the RHS please use rep() to
make this intent clear to readers of your code.
有人可以指出我在这里做错了什么吗?提前致谢。
这是一种方法,
df[, .(val = tstrsplit(gsub("[][']", "", val), ",", fixed=TRUE)), by = id]
# id val
# <num> <list>
# 1: 1 hello
# 2: 1 world
# 3: 2 hi
# 4: 3 so
# 5: 3 there
它删除了所有方括号和单引号,然后将所有 val
字符串连接成一个字符串(,
-折叠),然后 tstrsplit
按原意将它们连接起来. by=id
确保我们不会无意中组合不同的 val
,并且 id
保留在输出中。
如果你想看到分组,组合,然后拆分的步骤,那么可以做到
df1[, .(val = paste(gsub("[][']", "", val), collapse = ",")), by = id]
# id val
# <num> <char>
# 1: 1 hello, world
# 2: 2 hi
# 3: 3 so, there
df1[, .(val = paste(gsub("[][']", "", val), collapse = ",")), by = id
][, .(val = tstrsplit(val, ",", fixed = TRUE)), by = id]
# id val
# <num> <list>
# 1: 1 hello
# 2: 1 world
# 3: 2 hi
# 4: 3 so
# 5: 3 there
请注意 rep(id,...)
的错误建议很好,只是您需要做更多的工作才能知道每个 id
重复多少次;将它用作分组变量可以减轻这种需要,但会花费少量的执行时间(因为它对每个组执行一次 tstrsplit
而不是一起执行)。
和tidyverse
,我们可以用str_extract_all
和unnest
library(dplyr)
library(tidyr)
library(stringr)
df %>%
mutate(val = str_extract_all(val, '\w+')) %>%
unnest(val)
# A tibble: 5 x 2
id val
<dbl> <chr>
1 1 hello
2 1 world
3 2 hi
4 3 so
5 3 there
从您拥有的数据结构来看,您似乎拥有一个 python 数据集。您可以为此使用 reticulate
:
library(reticulate)
ast <- import('ast')
df_python <- r_to_py(df)
df_python$assign(val = df_python$val$transform(ast$literal_eval))$explode('val')
id val
0 1.0 hello
0 1.0 world
1 2.0 hi
2 3.0 so
2 3.0 there
你可以直接做:
df[, .(val = tstrsplit(gsub('[^a-z,]', '',val), ',')), by = 'id']
id val
1: 1 hello
2: 1 world
3: 2 hi
4: 3 so
5: 3 there
我想你可以使用 eval
+ str2lang
> df[, .(val = eval(str2lang(gsub("\[(.*)\]", "c(\1)", val)))), id]
id val
1: 1 hello
2: 1 world
3: 2 hi
4: 3 so
5: 3 there
我以下面的data.table
为例
df = data.table(id = c(1, 2, 3), val=c("['hello', 'world']", "['hi']", "['so', 'there']"))
我想将类似对象的列表拆分为单独的行,并重复 id
。所以我想要的预期data.table
是下面的
df2 = data.table(id = c(1, 1, 2, 3, 3), val=c("hello", "world", "hi", "so", "there"))
我尝试了以下方法
df[, c("test") := tstrsplit(val, ",", fixed=TRUE)]
但是,我得到了以下错误
Error in
[.data.table
(df, ,:=
(c("test"), tstrsplit(val, ",", fixed = TRUE))) : Supplied 2 items to be assigned to 3 items of column 'test'. If you wish to 'recycle' the RHS please use rep() to make this intent clear to readers of your code.
有人可以指出我在这里做错了什么吗?提前致谢。
这是一种方法,
df[, .(val = tstrsplit(gsub("[][']", "", val), ",", fixed=TRUE)), by = id]
# id val
# <num> <list>
# 1: 1 hello
# 2: 1 world
# 3: 2 hi
# 4: 3 so
# 5: 3 there
它删除了所有方括号和单引号,然后将所有 val
字符串连接成一个字符串(,
-折叠),然后 tstrsplit
按原意将它们连接起来. by=id
确保我们不会无意中组合不同的 val
,并且 id
保留在输出中。
如果你想看到分组,组合,然后拆分的步骤,那么可以做到
df1[, .(val = paste(gsub("[][']", "", val), collapse = ",")), by = id]
# id val
# <num> <char>
# 1: 1 hello, world
# 2: 2 hi
# 3: 3 so, there
df1[, .(val = paste(gsub("[][']", "", val), collapse = ",")), by = id
][, .(val = tstrsplit(val, ",", fixed = TRUE)), by = id]
# id val
# <num> <list>
# 1: 1 hello
# 2: 1 world
# 3: 2 hi
# 4: 3 so
# 5: 3 there
请注意 rep(id,...)
的错误建议很好,只是您需要做更多的工作才能知道每个 id
重复多少次;将它用作分组变量可以减轻这种需要,但会花费少量的执行时间(因为它对每个组执行一次 tstrsplit
而不是一起执行)。
和tidyverse
,我们可以用str_extract_all
和unnest
library(dplyr)
library(tidyr)
library(stringr)
df %>%
mutate(val = str_extract_all(val, '\w+')) %>%
unnest(val)
# A tibble: 5 x 2
id val
<dbl> <chr>
1 1 hello
2 1 world
3 2 hi
4 3 so
5 3 there
从您拥有的数据结构来看,您似乎拥有一个 python 数据集。您可以为此使用 reticulate
:
library(reticulate)
ast <- import('ast')
df_python <- r_to_py(df)
df_python$assign(val = df_python$val$transform(ast$literal_eval))$explode('val')
id val
0 1.0 hello
0 1.0 world
1 2.0 hi
2 3.0 so
2 3.0 there
你可以直接做:
df[, .(val = tstrsplit(gsub('[^a-z,]', '',val), ',')), by = 'id']
id val
1: 1 hello
2: 1 world
3: 2 hi
4: 3 so
5: 3 there
我想你可以使用 eval
+ str2lang
> df[, .(val = eval(str2lang(gsub("\[(.*)\]", "c(\1)", val)))), id]
id val
1: 1 hello
2: 1 world
3: 2 hi
4: 3 so
5: 3 there