R-拆分字母数字字符观测值,每个字母因子列中包含每个观测值的数值

R-拆分字母数字字符观测值,每个字母因子列中包含每个观测值的数值,r,regex,string,R,Regex,String,我不太确定如何最好地表达我想做的事情的标题 我有一个如下所示的数据框: ID = c(1, 2, 3, 4, 5, 6, 7) observation = c("a2", NA, "b3", "c5", NA, "b", "a3") df <- data.frame(cbind(ID, observation)) df ID observation 1 1 a2 2 2 <NA> 3 3 b3 4 4

我不太确定如何最好地表达我想做的事情的标题

我有一个如下所示的数据框:

 ID = c(1, 2, 3, 4, 5, 6, 7)
 observation = c("a2", NA, "b3", "c5", NA, "b", "a3")
 df <- data.frame(cbind(ID, observation))

 df

  ID observation
1  1          a2
2  2        <NA>
3  3          b3
4  4          c5
5  5        <NA>
6  6           b
7  7          a3
我想要的输出是一个数据框,它将观察值按数字和字母拆分,每个唯一字母都有一个新的列,其中每一行都包含该字母的相关观察值

所需的输出应如下所示:

desired_df <- data.frame(cbind(ID, a = c(2, NA, 0, 0, 0 , 0, 3), 
                                   b = c(0, NA, 3, 0, 0, 0, 0),
                                   c = c(0, NA, 0, 5, 0, 0, 0)))
desired_df

  ID  a  b  c
1  1  2  0  0
2  2 NA NA NA
3  3  0  3  0
4  4  0  0  5
5  5  0 NA NA
6  6  0  0  0
7  7  3  0  0
我尝试通过使用正则表达式将观察值拆分为字母和数字,并将结果保存到新列中来实现这一点:

library(stringr)
char <- unlist(str_replace_all(observation, "[[:digit:]]", ""))
num <- unlist(str_extract(observation, "[[:digit:]]"))
df_new <- cbind(ID, char, num)
df_new

  ID char  num
1  1    a    2
2  2 <NA> <NA>
3  3    b    3
4  4    c    5
5  5 <NA> <NA>
6  6    b <NA>
7  7    a    3
然后根据这个问题的答案,尝试将char转换成factors,再转换成二进制形式

然后,我尝试用该行的df_new1$num中的对应值替换每个1观察值,基于以下答案:

输出错误的结果。我一直在努力想办法解决这个问题。只要a、b、c列中的值正确,我同意将所有非1值替换为0

我不确定是否将字母和数字拆分为单独的列,并尝试将字母作为因子替换为二进制观察值是解决我的原始问题的最佳方法,我愿意接受任何可行的方法

我的真实数据帧是由一个脚本生成的,该脚本从.txt文件中提取模式,其中字母数字的观察值因文件而异。我需要的东西,将工作的任何独特的字母被分配到字符列

由于我是R的新手,我非常感谢您对我的建议或帮助。我仍然熟悉SO礼仪,并希望您能就如何改进问题和/或复制示例提出意见

您可以使用extract from tidyr将观察值拆分为var和value列,然后使用spread重塑表格。请注意,由于ID==2中的NA值,现在这是它自己的列。select将删除该列:

library(dplyr)
library(tidyr)

df %>%
  extract(observation, c("var", "value"), regex = "([a-z])?(\\d)?") %>%
  spread(var, value) %>%
  select(-`<NA>`)
结果:


因为您提到非数字值可以是0或NA


您可以使用tidyr包中的spread函数。df_new您的欲望输出有一个ID==7行。这是打字错误吗?@UseR,是的,谢谢你抓住了。我在编辑中修复了它。谢谢!这对于示例数据帧非常有效,但是当我尝试将其应用于实际数据帧时,我得到一个错误:var必须计算为单个数字或列名,而不是列表@用户:关于如何排除故障有什么建议吗?@Phono如果不查看您的真实数据,就很难判断问题出在哪里。您能否提供一个可能更好地表示真实数据的示例数据集?这对于示例df和我的实际df都很有效。谢谢
df_new2 <- data.frame(with(df_new1, ifelse(df_new1 == 1, df_new1$num, 0)))

df_new2
  ID char num  a  b  c
1  1    0   0  1  0  0
2  0   NA  NA NA NA NA
3  0    0   0  0  2  0
4  0    0   0  0  0  3
5  0   NA  NA NA NA NA
6  0    0  NA  0 NA  0
7  0    0   0  2  0  0
library(dplyr)
library(tidyr)

df %>%
  extract(observation, c("var", "value"), regex = "([a-z])?(\\d)?") %>%
  spread(var, value) %>%
  select(-`<NA>`)
  ID    a    b    c
1  1    2 <NA> <NA>
2  2 <NA> <NA> <NA>
3  3 <NA>    3 <NA>
4  4 <NA> <NA>    5
5  5 <NA> <NA> <NA>
6  6    3 <NA> <NA>
library(tidyverse)
df %>%
  nest(-ID) %>%
  mutate(data = map(data, ~data.frame(key = gsub("\\d", "", unlist(.x)), val = gsub("\\D", "", unlist(.x))))) %>%
  unnest() %>%
  spread(key, val, fill = 0) %>%
  select(-ncol(.)) %>%
  replace(.=="", 0)

  # ID    a     b     c    
  # <fct> <chr> <chr> <chr>
# 1 1     2     0     0    
# 2 2     0     0     0    
# 3 3     0     3     0    
# 4 4     0     0     5    
# 5 5     0     0     0    
# 6 6     3     0     0    
# There were 14 warnings (use warnings() to see them)