我有一个 csv 文件,其中一列包含一个 numpy 数组。读取 csv 文件时,结果列将是字符类型,因为它全部包含在字符串中。 我想将它解析成一个单独的数据框来分析数据。
作为 csv:
first_column,second_column
a,"[[1,2],[3,4]]"
b,"[[5,6],[7,8]]"
c,"[[9,10],[11,12]]"
作为数据框:
df <- data.frame(first_column = c("a","b","c"),
second_column = c("[[1,2],[3,4]]","[[5,6],[7,8]]","[[9,10],[11,12]]"))
因为我不知道有任何可以从字符串中提取数组的直接解析函数,所以我开始进行字符串操作。
去掉外面的
[]
字符:
> df %>% mutate(second_column = str_replace_all(second_column, c("^\\[" = "","]$" = "")))
first_column second_column
1 a [1,2],[3,4]
2 b [5,6],[7,8]
3 c [9,10],[11,12]
然而,从现在开始我不知道如何进行。
最后生成的数据框应该是这样的:
col_1 col_2
1 1 2
2 3 4
3 5 6
4 7 8
5 9 10
6 11 12
注意真实的dataframe中有更多的列和更多的行
将出现的 ],[ 替换为换行符,将方括号替换为空格并使用
read.table
阅读它。
df$second_column |>
gsub("\\],\\[", "\n", x = _) |>
chartr("[]", " ", x = _) |>
read.table(text = _, sep = ",")
给予:
V1 V2
1 1 2
2 3 4
3 5 6
4 7 8
5 9 10
6 11 12
这是一个使用
tidyverse
的 hacky 解决方案:
df <- data.frame(first_column = c("a","b","c"),
second_column = c("[[1,2],[3,4]]","[[5,6],[7,8]]","[[9,10],[11,12]]"))
library(tidyverse)
df %>%
mutate(second_column = str_replace_all(second_column, c("^\\[" = "","]$" = "")),
second_column = gsub("\\[|\\]", "", second_column)) %>%
separate(second_column, into = c("col_1", "col_2", "col_3", "col_4"), sep = ",") %>%
pivot_longer(-first_column) %>%
mutate(name = case_when(name == "col_3" ~ "col_1",
name == "col_4" ~ "col_2",
.default = name)) %>%
select(-first_column) %>%
pivot_wider(names_from = name, values_from = value, values_fn = list) %>%
unnest(cols = c(col_1, col_2))
#> # A tibble: 6 × 2
#> col_1 col_2
#> <chr> <chr>
#> 1 1 2
#> 2 3 4
#> 3 5 6
#> 4 7 8
#> 5 9 10
#> 6 11 12
A base R 方法处理给定列上的任意数量的行。
setNames(
data.frame(Vectorize(\(x) as.numeric(x))(
data.frame(do.call(rbind,
sapply(lapply(strsplit(df$second_column, "\\],\\["),
gsub, pattern="\\[|\\]", replacement=""), strsplit, ","))))),
c("col_1", "col_2"))
col_1 col_2
1 1 2
2 3 4
3 5 6
4 7 8
5 9 10
6 11 12
py_eval
的技巧来自reticulate
library(reticulate)
with(
df,
as.data.frame(
do.call(
rbind,
py_eval(gsub("]], [[", "],[",
toString(second_column),
fixed = TRUE
))
)
)
)
给予
V1 V2
1 1 2
2 3 4
3 5 6
4 7 8
5 9 10
6 11 12