我不太确定如何最好地标题我想做什么。
我有一个如下所示的数据框:
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
然后尝试根据此SO Question
的答案将char转换为二进制形式的因子df_new <- data.frame(cbind(df, sapply(levels(as.factor((char))),
function(x) as.integer(x == char))))
ID char num a b c
1 1 a 2 1 0 0
2 2 <NA> <NA> NA NA NA
3 3 b 3 0 1 0
4 4 c 5 0 0 1
5 5 <NA> <NA> NA NA NA
6 6 b <NA> 0 1 0
7 7 a 3 1 0 0
然后,我尝试根据此SO question的答案,用该行的df_new1 $ num中的相应值替换每个1个观察值:
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
哪个输出错误的结果。我一直在努力解决这个问题。只要列a,b,c中的值正确,我就可以将所有非1值替换为0。
我不确定是否将字母和数字拆分为单独的列,并尝试将字母的二进制观察替换为因子甚至是尝试解决原始问题的最佳方法,并且对任何有效的方法持开放态度。
我的真实数据框是由一个脚本生成的,该脚本从.txt文件中提取模式,其中字母数字观察因文件而异。我需要的东西适用于任何分配给char列的唯一字母。
我很感激任何建议或帮助解决这个问题,因为我是R的新手。我仍然熟悉SO礼仪,并会对如何改进问题和/或可重复的例子表示感谢。
答案 0 :(得分:2)
您可以使用extract
中的tidyr
将observation
拆分为var
和value
列,然后使用spread
重新整形表格。请注意,由于<NA>
中的NA值,ID == 2
现在是它自己的列。 select
删除了该列:
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>
答案 1 :(得分:1)
由于您提到非数字值可以是0
或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)