使用R中的子字符串和gregexpr创建新列

时间:2016-01-31 00:46:03

标签: r substring

我有一个表,其中一列是这样的字符串:foo%

大约有20000行,我需要为每一行创建一个包含此子字符串的新列:aaaaaaa_bbbbbb_ccccc_1111111

经过一些研究后,我发现使用aaaaaaa_bbbbbb_ccccc"substring"对我有用,而且当我为每一行使用这样的命令时(或者如果我选择一些行),它确实可以正常工作:

"gregexpr"

但是我想在没有循环的情况下使用它:

for (i in 1:nrow(table)){ table$column[i] <- substring(table$column[i], 1, (gregexpr("_", table$column[i])[[1]][3])-1) }

但是在这种情况下,新列的子字符串与我想要的模式不匹配,有时它们是正确的,有时候它们是随机的长度。

有人知道可能导致这些奇怪结果的原因吗?

1 个答案:

答案 0 :(得分:0)

假设您的数据如下所示:

df <- as.data.frame(t(sapply(seq(10), function(x) c(x,paste(paste(sapply(seq(3),function(i) paste(rep(letters[sample(seq(26),1)],7),collapse="")),collapse="_"),paste(rep(as.character(sample(seq(9),1)),7),collapse=""),sep="_")))))
colnames(df) <- c("id","column")
df
#    id                          column
# 1   1 wwwwwww_kkkkkkk_bbbbbbb_7777777
# 2   2 iiiiiii_wwwwwww_qqqqqqq_5555555
# 3   3 iiiiiii_vvvvvvv_bbbbbbb_1111111
# 4   4 hhhhhhh_xxxxxxx_rrrrrrr_4444444
# 5   5 sssssss_eeeeeee_eeeeeee_8888888
# 6   6 ooooooo_ddddddd_rrrrrrr_9999999
# 7   7 yyyyyyy_rrrrrrr_hhhhhhh_1111111
# 8   8 yyyyyyy_rrrrrrr_lllllll_4444444
# 9   9 ggggggg_ggggggg_iiiiiii_6666666
# 10 10 ccccccc_lllllll_jjjjjjj_2222222

你想要这样的东西:

df
#    id                  column
# 1   1 wwwwwww_kkkkkkk_bbbbbbb
# 2   2 iiiiiii_wwwwwww_qqqqqqq
# 3   3 iiiiiii_vvvvvvv_bbbbbbb
# 4   4 hhhhhhh_xxxxxxx_rrrrrrr
# 5   5 sssssss_eeeeeee_eeeeeee
# 6   6 ooooooo_ddddddd_rrrrrrr
# 7   7 yyyyyyy_rrrrrrr_hhhhhhh
# 8   8 yyyyyyy_rrrrrrr_lllllll
# 9   9 ggggggg_ggggggg_iiiiiii
# 10 10 ccccccc_lllllll_jjjjjjj

您只需使用sub

即可
df$column <- sub("_[0-9]+","",df$column)

sub允许您替换character向量中模式的第一个匹配项。此外,它是矢量化的,这允许我们避免显式循环。在这里,我们使用您要删除«numeric»部分的事实,但如果您只是想在最后_之后排除该部分,您可以考虑这样做:

df$column <- sub("_[0-9a-z]+$","",df$column)

编辑(以发表评论):

我认为没有办法避免使用gregexpr进行循环。

如果我想要一个单行,无论如何,我可能会这样实现它:

df$column <- substring(df$column, sapply(gregexpr("_", df$column), function(i) i[1]+1), sapply(gregexpr("_", df$column), function(i) i[3]-1))

或者,我们可以继续sub。如果您还想删除字符串的第一部分,请对其进行两次处理:

df$column <- sub("^[0-9a-z]+_","",df$column)
df$column <- sub("_[0-9a-z]+$","",df$column)

工作完成了。

最后,您还可以考虑使用strsplit

df$column <- sapply(df$column, function(x) paste(strsplit(x,"_")[[1]][2:3],collapse="_"))

(对于后者,请确保您的专栏为character而不是factor