首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将字符串列分隔为多个列,每个列包含一个字符串的单个字符,字符串长度不等,没有分隔符?

如何将字符串列分隔为多个列,每个列包含一个字符串的单个字符,字符串长度不等,没有分隔符?
EN

Stack Overflow用户
提问于 2019-09-13 23:56:43
回答 3查看 116关注 0票数 2

我的数据框架是:

代码语言:javascript
复制
data.frame(stringsAsFactors=FALSE,
       A = c("1234", "abc.", "e-2.1ad"),
       B = c("5-4", "1-0", "a,d")
)

我希望将这些列分隔为包含单个字符的多个列。

我发现的其他答案都涉及到使用一些正则表达式、模式或分隔符,正如您所看到的,在这里我不能这样做,或者使用sapply (使用这个位置,但对我来说它不起作用)的复杂解决方案。我确信有一个更优雅的解决方案,如果可能的话,我非常希望使用tidyr的解决方案,但是不管它是干净的还是很受欢迎的。

这是它应该喜欢的,毕竟是这样说和做的:

代码语言:javascript
复制
 newdf <- data.frame(stringsAsFactors=FALSE,
      A1 = c("1", "a", "e"),
      A2 = c("2", "b", "-"),
      A3 = c("3", "c", "2"),
      A4 = c("4", ".", "."),
      A5 = c(NA, NA, 1),
      A6 = c(NA, NA, "a"),
      A7 = c(NA, NA, "d"),
      B1 = c("5", "1", "a"),
      B2 = c("-", "-", ","),
      B3 = c("4", "0", "d")
)

而且,如果答案不仅仅是抛出一两个函数,我会非常感谢你能解释一下你是怎么做的,而不仅仅是解决方案本身。谢谢!

稍后的编辑:我几乎可以使用qdap包完成它,但是我可以绕过它,从字符串的开头就用字符填充应该是NAs的内容(因为字符串的长度不等)。非常奇怪的行为,没有在文档中解释,否则是一个非常有希望的功能。

在我试图解决这个问题时,我注意到了另一个奇怪的行为,那就是自动地将角色转化为因素。然而,我无法确定这条路在哪里发生。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-09-14 02:37:40

有许多潜在的选择,取决于您感兴趣的细节。见上文关于5-432中失踪32人的评论。

考虑的一种可能性是来自str_split_fixed包的stringr

代码语言:javascript
复制
str_split_fixed("1234", "", 7)

     [,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,] "1"  "2"  "3"  "4"  ""   ""   ""  

空模式"“将按字符拆分,在本例中,尝试返回7段作为字符矩阵(最后3个空字符串)。现在,如果没有可用的字符,则返回一个空字符串,而不是NA。(见github问题)。

如果列数是基于A和B列的最大字符数(例如7和5),则可以执行以下操作:

代码语言:javascript
复制
as.data.frame(lapply(df, function(x) str_split_fixed(x, "", n=max(nchar(x)))))

  A.1 A.2 A.3 A.4 A.5 A.6 A.7 B.1 B.2 B.3 B.4 B.5
1   1   2   3   4               5   -   4   3   2
2   a   b   c   .               1   -   0        
3   e   -   2   .   1   a   d   a   ,   d        

注意:之后用NA替换空字符串:

代码语言:javascript
复制
df[df==""] <- NA

  A.1 A.2 A.3 A.4  A.5  A.6  A.7 B.1 B.2 B.3  B.4  B.5
1   1   2   3   4 <NA> <NA> <NA>   5   -   4    3    2
2   a   b   c   . <NA> <NA> <NA>   1   -   0 <NA> <NA>
3   e   -   2   .    1    a    d   a   ,   d <NA> <NA>
票数 2
EN

Stack Overflow用户

发布于 2019-09-14 01:56:11

这是我的tidyverse解决方案。写一个函数对我来说是新的,任何改进的建议都将不胜感激。

代码语言:javascript
复制
library(tidyverse)
df <- data.frame(stringsAsFactors=FALSE,
        A = c("1234", "abc.", "e-2.1ad"),
        B = c("5-432", "1-0", "a,d"))    

a_split<- str_split(df$A, "")
b_split<- str_split(df$B, "")
f1 <- function(num, s)(c(s[[1]][num], s[[2]][num], s[[3]][num]))
x <- c(1:7)
all_a <- lapply(x, f1, a_split)
x <- c(1:5)
all_b <- lapply(x, f1, b_split)
票数 1
EN

Stack Overflow用户

发布于 2019-09-14 02:33:45

我们可以从cSplit中使用splitstackshape,并将列AB中的每个字符拆分为单独的列。

代码语言:javascript
复制
df1 <- splitstackshape::cSplit(df, c('A', 'B'), sep = '', stripWhite = FALSE)
df1

#   A_1 A_2 A_3 A_4 A_5  A_6  A_7 B_1 B_2 B_3 B_4 B_5 B_6 B_7
#1:   1   2   3   4  NA <NA> <NA>   5   -   4   3   2  NA  NA
#2:   a   b   c   .  NA <NA> <NA>   1   -   0  NA  NA  NA  NA
#3:   e   -   2   .   1    a    d   a   ,   d  NA  NA  NA  NA

但是,这为我提供了一些NA for B的额外列,这些列可以使用Filter删除。

代码语言:javascript
复制
Filter(function(x) any(!is.na(x)), df1)
#   A_1 A_2 A_3 A_4 A_5  A_6  A_7 B_1 B_2 B_3 B_4 B_5
#1:   1   2   3   4  NA <NA> <NA>   5   -   4   3   2
#2:   a   b   c   .  NA <NA> <NA>   1   -   0  NA  NA
#3:   e   -   2   .   1    a    d   a   ,   d  NA  NA

数据

代码语言:javascript
复制
df <- data.frame(stringsAsFactors=FALSE,
             A = c("1234", "abc.", "e-2.1ad"),
             B = c("5-432", "1-0", "a,d"))
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57931444

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档