假设您已获得以下数据框:
a <- data.frame(var = c(",1,2,3,", ",2,3,5,", ",1,3,5,5,"))
我正在寻找的是在a中创建变量flag_1,...,flag_7,其中包含各个值出现次数的信息。对于a,我希望得到以下结果:
var flag_1 flag_2 flag_3 flag_4 flag_5
",1,2,3," 1. 1. 1. 0. 0.
",2,3,5," 0. 1. 1. 0. 1.
",1,3,5,5," 1. 0. 1. 0. 2.
我设法使用嵌套的for循环和if条件获得结果,但必须有更好的(更美观和更好的)解决方案。
答案 0 :(得分:3)
一个选项是strsplit
,table
,然后cbind
原始数据
cbind(a, do.call(rbind, lapply(strsplit(as.character(a$var), ","),
function(x) table(factor(x[nzchar(x)], levels = 1:5, labels = paste0("flag_", 1:5))))))
# var flag_1 flag_2 flag_3 flag_4 flag_5
#1 ,1,2,3, 1 1 1 0 0
#2 ,2,3,5, 0 1 1 0 1
#3 ,1,3,5,5, 1 0 1 0 2
另一种选择是使用tidyverse
library(tidyverse)
str_extract_all(a$var, "[0-9]") %>%
map(~ as.integer(.x) %>%
as_tibble) %>%
bind_rows(.id = 'grp') %>%
count(grp, value = factor(value, levels = min(value):max(value))) %>%
spread(value, n, drop = FALSE, fill = 0) %>%
select(-grp) %>%
bind_cols(a, .) %>%
rename_at(vars(matches("^[0-9]+$")), ~ paste0("flag_", .))
# var flag_1 flag_2 flag_3 flag_4 flag_5
#1 ,1,2,3, 1 1 1 0 0
#2 ,2,3,5, 0 1 1 0 1
#3 ,1,3,5,5, 1 0 1 0 2
答案 1 :(得分:1)
首先,不要将字符串变成因子。没有什么好处。
a <- data.frame(var = c(",1,2,3,", ",2,3,5,", ",1,3,5,5,"),
stringsAsFactors = FALSE)
如果我们采取小步骤,从字符串到表格就足够了。在这里,我每步编写(或重命名)一个函数,然后一次使用lapply
一个步骤。如果愿意的话,你可以将它们串在一个管道中,但这大致就是这些步骤。
首先,我从字符串中提取数字。这涉及拆分逗号,删除空字符串,你有那些因为你可以用逗号开始和结束一个字符串,但除此之外,该步骤不是必需的。然后我们需要将字符串转换为数字,计算我们每次看到的频率(我们可以分别用as.numeric
和table
函数来做),然后这只是映射观察到的问题计入一个表格,其中还包括我们未观察到的表格。
pick_indices <- function(str) unlist(strsplit(str, split = ","))
remove_empty <- function(chrs) chrs[nchar(chrs) > 0]
get_indices <- as.numeric
to_counts <- table
to_flag_vect <- function(counts, len) {
vec <- rep(0, len)
names(vec) <- 1:len
vec[names(counts)] <- counts
vec
}
strings <- lapply(a$var, pick_indices)
cleaned <- lapply(strings, remove_empty)
indices <- lapply(cleaned, get_indices)
counts <- lapply(indices, to_counts)
flags <- lapply(counts, to_flag_vect, len = 5)
我们现在在列表中有标记计数,因此要使用您想要的列名将其放入所需的表中,我们只需执行此操作:
tbl <- do.call(rbind, flags)
colnames(tbl) <- paste0("flag_", 1:5)
tbl
完成。
答案 2 :(得分:0)
将值拆分并取消列入具有适当级别的因子
x = strsplit(a$var, ",")
xp = factor(unlist(x), levels = seq_len(5))
创建一个索引,将xp
的值映射到它们来自的行
i = rep(seq_along(x), lengths(x))
使用xtabs()
按行交叉制表
xt = xtabs(~ i + xp)
和cbind()
结果的矩阵表示形式为原始
> cbind(a, unclass(xt))
var 1 2 3 4 5
1 ,1,2,3, 1 1 1 0 0
2 ,2,3,5, 0 1 1 0 1
3 ,1,3,5,5, 1 0 1 0 2