【问题标题】:Transforming string column to specific data.frame将字符串列转换为特定的data.frame
【发布时间】:2021-11-23 02:23:22
【问题描述】:

期望的输出

需要以下输出

df2 <-
  data.frame(
    v1 = c(1100001, 1100002, 1100003, 1100004, 1100005)
  , v2 = c("A R", "W R", "A K", "M", "A C")
  , v3 = c("P", "G P", "G P", "P", "P")
  , v4 = c(110, 161, 129, 132, "Absent")
  , v5 = c(55, 80.5, 64.5, 66,  "Absent")
    )
df2

       v1  v2  v3     v4     v5
1 1100001 A R   P    110     55
2 1100002 W R G P    161   80.5
3 1100003 A K G P    129   64.5
4 1100004   M   P    132     66
5 1100005 A C   P Absent Absent

这是我原来的data.frame

df1 <-
  structure(list(value = c(
"1100001     A R                P             110    55", 
"1100002     W R                 G P 161    80.5", 
"1100003     A K                  G P 129    64.5", 
"1100004     M                      P             132    66",
"1100005     A C                     P             Absent    Absent"
)), row.names = c(NA, -5L), class = c("data.frame")
)

df1

                                                              value
1            1100001     A R                P             110    55
2                   1100002     W R                 G P 161    80.5
3                  1100003     A K                  G P 129    64.5
4        1100004     M                      P             132    66
5 1100005     A C                     P             Absent    Absent

使用来自splitstackshapecSplit 函数,但无法获得所需的输出。任何点。

library(splitstackshape)
cSplit(indt = df1, splitCols = "value", sep = " ")

   value_1 value_2 value_3 value_4 value_5 value_6 value_7
1: 1100001       A       R       P     110      55      NA
2: 1100002       W       R       G       P     161    80.5
3: 1100003       A       K       G       P     129    64.5
4: 1100004       M       P     132      66      NA      NA
5: 1100005       A       P  Absent  Absent      NA      NA

【问题讨论】:

  • 将“GP 161”分成两个变量的规则是什么。另外,变量之间是否有制表符或空格?

标签: r string text tidyverse splitstackshape


【解决方案1】:

我们假设一个新字段在两个或多个空格之后开始,或者一个空格后跟一个数字,其中该数字是下一个字段的开始。用逗号替换此类分隔符,然后将read.tablesep="," 一起使用

df1$value |>
  gsub(pattern = "  +| (?=\\d)", replacement = ",", perl = TRUE) |>
  textConnection(name = "") |>
  read.table(sep = ",")

给出这个data.frame:

       V1  V2  V3     V4     V5
1 1100001 A R   P    110     55
2 1100002 W R G P    161   80.5
3 1100003 A K G P    129   64.5
4 1100004   M   P    132     66
5 1100005   A   P Absent Absent

会话日志

> df1 <-
+   structure(list(value = c(
+ "1100001     A R                P             110    55", 
+ "1100002     W R                 G P 161    80.5", 
+ "1100003     A K                  G P 129    64.5", 
+ "1100004     M                      P             132    66",
+ "1100005     A C                     P             Absent    Absent"
+ )), row.names = c(NA, -5L), class = c("data.frame")
+ )
> 
> df2 <-
+   data.frame(
+     v1 = c(1100001, 1100002, 1100003, 1100004, 1100005)
+   , v2 = c("A R", "W R", "A K", "M", "A C")
+   , v3 = c("P", "G P", "G P", "P", "P")
+   , v4 = c(110, 161, 129, 132, "Absent")
+   , v5 = c(55, 80.5, 64.5, 66,  "Absent")
+     )
> 
> df2a <- df1$value |>
+   gsub(pattern = "  +| (?=\\d)", replacement = ",", perl = TRUE) |>
+   textConnection(name = "") |>
+   read.table(sep = ",")
> 
> all(df2 == df2a)
[1] TRUE

【讨论】:

  • 我的错。我在df1 中有错字,已更正。更正后,给定的代码会引发错误。有什么想法吗。请。
  • 不适合我。我在答案末尾添加了会话日志。它不会抛出错误,并且 df2a 的所有元素都等于 df2 的相应元素。
【解决方案2】:

1.假设分隔规则是:a)多个空格 b)字母和空格后面的数字要分开

2.我们确保所有即将成为变量的变量由多个空格分隔(使用gsub一个空格字母和数字之间替换为两个空格)

3.然后我们使用tidyr::separate将字符串分隔成变量,使用两个或多个空格作为分隔符

library(dplyr)
library(tidyr)
df1 %>% 
  mutate(value = gsub("([A-z])( )([0-9])", "\\1  \\3", value)) %>% 
  separate(value, c(paste0("v", 1:5)),"[ ]{2,}")

返回:

       v1  v2  v3     v4     v5
1 1100001 A R   P    110     55
2 1100002 W R G P    161   80.5
3 1100003 A K G P    129   64.5
4 1100004   M   P    132     66
5 1100005   A   P Absent Absent

编辑

关于原始示例中未包含的新约束(数字和字母之间只有一个空格):

建议的解决方案:

我们只是重复使用“反转”正则表达式添加额外空格的命令。这样数字和字母之间的任何单个空格都会得到一个额外的空格,然后会被 separate 调用分隔

df1 %>% 
  mutate(value = gsub("([A-z])( )([0-9])", "\\1  \\3", value)) %>% 
  mutate(value = gsub("([0-9])( )([A-z])", "\\1  \\3", value)) %>% 
  separate(value, c(paste0("v", 1:5)),"[ ]{2,}")

【讨论】:

  • 感谢@dario 的回答。缺少第三列缺少某些部分。
  • 很抱歉,你当然是对的!同样的行上也缺少第一个数字...我修复了正则表达式,现在它可以按预期工作了!
  • 您的代码提供的输出非常接近我的原始数据所需的输出。但是,对于某些行,星号和字母之间的相同是一个空格,例如1100006 B R。任何想法
  • @MYaseen208 我已经更新了解决新约束的答案
猜你喜欢
  • 2014-10-31
  • 2016-03-03
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
  • 2011-02-20
  • 2020-08-10
  • 2017-10-03
相关资源
最近更新 更多