【问题标题】:Split character column value into 4 new value columns using gsub and drop values of original column使用 gsub 将字符列值拆分为 4 个新值列并删除原始列的值
【发布时间】:2021-06-07 13:16:35
【问题描述】:

我有一列包含这样的数组值:

 [[["0.10", "35"], ["0.2", "36"]], [["5.1", "2"], ["90.2", "2"]]]

我需要 4 个单独列中的最后两个(在本例中:[["5.1", "2"], ["90.2", "2"]]) 但只有他们的价值观:

5.1 2 90.22(在不同的列中)

我知道我可以使用 tidyR 来实现这一点,如下所述:split character data into numbers and letters

    df %>%
  separate(mycol, 
           into = c("text", "num"), 
           sep = "(?<=[A-Za-z])(?=[0-9])"
           )

但到目前为止,每一次尝试和每一次尝试都失败了。我无法仅访问最后 2(或 4)项。

如有任何想法,我将不胜感激。。谢谢

【问题讨论】:

  • 试试stringr::str_extract_all(x, "\\d+(?:\\.\\d+)?(?=(?:[^,]*,){0,3}[^,]*$)")
  • 您好维克托,谢谢!但是,这不会产生 4 个单独的列,只有 1 个包含所有 4 个值在“”中,如下所示:“0.10”、“35”、“0.2”和“36”。

标签: r regex multiple-columns gsub


【解决方案1】:

我们可以按行分组(rowwise),然后将带有fromJSON 的“mycol”元素转换为matrixes 的list,将unlist 转换为vector,将向量转换为数据.frame 使用 as.data.frame.list 包含 4 列,将其包装在 list 中,然后我们将 ungroupunnest list 列与 unnest_wider(来自 tidyr),最后,转换基于列的类型type.convert 的价值

library(dplyr)
library(jsonlite)
library(tidyr)
d %>%
  rowwise %>%
  mutate(newcol = list(setNames(as.data.frame.list(unlist(fromJSON(mycol, 
             simplifyVector  = FALSE)[[2]] )), paste0("X", 1:4)))) %>%
  ungroup %>%
  unnest_wider(c(newcol))   %>%
  type.convert(as.is = TRUE)

-输出

# A tibble: 3 x 5
#  mycol                                                                                 X1    X2    X3    X4
#  <chr>                                                                              <dbl> <int> <dbl> <int>
#1 "[[[\"0.10\", \"35\"], [\"0.2\", \"36\"]], [[\"5.1\", \"2\"], [\"90.2\", \"2\"]]]"   5.1     2  90.2     2
#2 "[[[\"0.10\", \"35\"], [\"0.2\", \"36\"]], [[\"5.1\", \"2\"], [\"90.2\", \"2\"]]]"   5.1     2  90.2     2
#3 "[[[\"0.10\", \"35\"], [\"0.2\", \"36\"]], [[\"5.1\", \"2\"], [\"90.2\", \"2\"]]]"   5.1     2  90.2     2

数据

d <- structure(list(mycol = c("[[[\"0.10\", \"35\"], [\"0.2\", \"36\"]], [[\"5.1\", \"2\"], [\"90.2\", \"2\"]]]", 
"[[[\"0.10\", \"35\"], [\"0.2\", \"36\"]], [[\"5.1\", \"2\"], [\"90.2\", \"2\"]]]", 
"[[[\"0.10\", \"35\"], [\"0.2\", \"36\"]], [[\"5.1\", \"2\"], [\"90.2\", \"2\"]]]"
)), class = "data.frame", row.names = c(NA, -3L))

【讨论】:

  • 感谢您的建议,但无论出于何种原因,此解决方案都不起作用。甚至没有通过错误,只是继续计算......
  • @IndiPsi 抱歉,代码中缺少关闭 )。你现在可以测试。我添加了一个可重现的示例
  • 您好,这行得通。惊人的!你能解释一下这个函数到底是做什么的吗?我知道 JSON 可以以某种方式处理数组,我猜?
  • @IndiPsi 我添加了一些解释。希望它有效
  • 非常感谢! :)
【解决方案2】:

这是一个基于正则表达式和@akrun 数据的base R 解决方案:

d1 <- sapply(strsplit(d$mycol, ","), function(x) gsub("(?!\\.)\\D", "", x, perl = T))

我们首先在逗号处拆分d,然后将结果传递给gsub函数,该函数删除任何不是数字(\\D)而不是.的东西。我们transpose 生成的数据框d1 将列转换为行并选择感兴趣的数据:

d2 <- as.data.frame(t(d1[5:8,]))
d2
   V1 V2   V3 V4
1 5.1  2 90.2  2
2 5.1  2 90.2  2
3 5.1  2 90.2  2

如果您想将结果与原始数据一起获得,那么cbind 并根据您的需要更改列名:

d3 <- cbind(d, d2)
names(d3) <- c("mycol", "x1", "x2", "x3", "x4")

结果:

d3
                                                             mycol  x1 x2   x3 x4
1 [[["0.10", "35"], ["0.2", "36"]], [["5.1", "2"], ["90.2", "2"]]] 5.1  2 90.2  2
2 [[["0.10", "35"], ["0.2", "36"]], [["5.1", "2"], ["90.2", "2"]]] 5.1  2 90.2  2
3 [[["0.10", "35"], ["0.2", "36"]], [["5.1", "2"], ["90.2", "2"]]] 5.1  2 90.2  2

【讨论】:

  • 确实如此,而且更经济一点。如果它有帮助,请考虑支持/接受它。
  • 嗨,我赞成 - 因为我是 Stackoverflow 的新手,所以可能需要一些时间才能计算在内。实际上,我发现另一个解决方案在我的情况下有点实用,因为我可以将它与更多功能连接起来,例如我修改它以使用更多数组来做同样的事情。但是,我很感激我收到了这两个完美的解决方案来解决我已经花费了我几个小时的问题。所以,非常感谢!
猜你喜欢
  • 2021-02-19
  • 1970-01-01
  • 2019-01-09
  • 1970-01-01
  • 2021-07-26
  • 2022-01-23
  • 2017-10-03
  • 2021-04-01
  • 1970-01-01
相关资源
最近更新 更多