如何从 csv/dataframe 列中的字符串解析数组数组

问题描述 投票:0回答:4

我有一个 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中有更多的列和更多的行

r arrays dataframe csv nested-lists
4个回答
2
投票

将出现的 ],[ 替换为换行符,将方括号替换为空格并使用

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

0
投票

这是一个使用

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

0
投票

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

0
投票

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
© www.soinside.com 2019 - 2024. All rights reserved.