【问题标题】:Tidying arrays of numbers in R data frame整理R数据框中的数字数组
【发布时间】:2021-12-29 14:54:03
【问题描述】:

如何整理下面的数据框

data.frame(a  = c(1,2), values = c("[1.1, 1.2, 1.3]", "[2.1, 2.2]"))

 a          values
1 [1.1, 1.2, 1.3]
2      [2.1, 2.2]

结果应该是

data.frame(a  = c(1,1,1,2,2), values = c(1.1, 1.2, 1.3, 2.1, 2.2))
  a values
 1    1.1
 1    1.2
 1    1.3
 2    2.1
 2    2.2

【问题讨论】:

    标签: r tidyverse tidyr


    【解决方案1】:

    我们可以在listunnest 中提取带有str_extract_all 的数字

    library(dplyr)
    library(stringr)
    library(tidyr)
    df1 %>%
        mutate(values = str_extract_all(values, "[0-9.]+")) %>% 
        unnest(values) %>% 
        type.convert(as.is = TRUE)
    

    -输出

    # A tibble: 5 × 2
          a values
      <int>  <dbl>
    1     1    1.1
    2     1    1.2
    3     1    1.3
    4     2    2.1
    5     2    2.2
    

    或者另一种选择是使用reticulate:py_eval 评估python 对象,然后使用unnest list

    library(reticulate)
    df1 %>%
        rowwise %>%
         mutate(values = list(py_eval(values))) %>%
         unnest(values)
    

    -输出

    # A tibble: 5 × 2
          a values
      <dbl>  <dbl>
    1     1    1.1
    2     1    1.2
    3     1    1.3
    4     2    2.1
    5     2    2.2
    

    数据

    df1 <- data.frame(a  = c(1,2), values = c("[1.1, 1.2, 1.3]", "[2.1, 2.2]"))
    

    【讨论】:

    • 您的reticulate:py_eval 很有创意。恭喜你,阿伦!
    【解决方案2】:

    另一种可能的解决方案:

    library(tidyverse)
    
    df <- data.frame(a  = c(1,2), values = c("[1.1, 1.2, 1.3]", "[2.1, 2.2]"))
    
    df %>% 
      separate(values, into=LETTERS[1:5], sep="\\[|,|\\]", fill="right",convert=T) %>% 
      pivot_longer(-a, values_drop_na = T) %>% 
      select(-name)
    
    #> # A tibble: 5 × 2
    #>       a value
    #>   <dbl> <dbl>
    #> 1     1   1.1
    #> 2     1   1.2
    #> 3     1   1.3
    #> 4     2   2.1
    #> 5     2   2.2
    

    【讨论】:

    • 当您使用separate 时。也可以使用separate_rowsdf1 %&gt;% mutate(values = str_remove_all(values, "\\[|\\]")) %&gt;% separate_rows(values, sep=",\\s*", convert = TRUE)
    • 谢谢,阿伦!聪明的方法,像往常一样!
    【解决方案3】:

    另一个使用 eval + expression + gsub 的基本 R 选项

    with(
      df,
      type.convert(
        setNames(
          rev(
            stack(
              sapply(
                setNames(values, a),
                function(x) eval(str2expression(gsub("\\[(.*)\\]", "c(\\1)", x)))
              )
            )
          ), names(df)
        ),
        as.is = TRUE
      )
    )
    

    给予

      a values
    1 1    1.1
    2 1    1.2
    3 1    1.3
    4 2    2.1
    5 2    2.2
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-22
      • 2023-03-06
      • 1970-01-01
      • 2016-02-06
      • 1970-01-01
      相关资源
      最近更新 更多