R正则表达式拆分名称字符串

lrpiutwd  于 2023-06-19  发布在  其他
关注(0)|答案(2)|浏览(165)

我有一个dataframe,其中以各种不同的格式列出了姓名,我想将这些姓名拆分为名、中名和姓。下面是一个具有不同名称格式的 Dataframe 示例:

df1 <- data.frame(name = c("Matt Smith", "Matt L. Smith", "Matt Louis Smith",
                           "M. Smith", "M.L. Smith", "M.L. Smith, Jr.", "M. Smith, Jr.", "Unknown"))

我有一个来自previous question的代码,它可以正确地分割非首字母,但是当第一个和中间的首字母都存在时,它就失败了。下面是代码及其输出:

names <- df1 %>%
  mutate(name = gsub('([A-Za-z\\.?]+) ([A-Za-z\\.]+ )?([A-Za-z]+)?', '\\1=\\2=\\3', name)) %>%
  separate(name, c("Collector.First.Name1", "Collector.Middle1", "Collector.Last.Name1"), "=")

Collector.First.Name1 Collector.Middle1 Collector.Last.Name1
1                  Matt                                  Smith
2                  Matt               L.                 Smith
3                  Matt            Louis                 Smith
4                    M.                                  Smith
5                  M.L.                                  Smith
6                  M.L.                             Smith, Jr.
7                    M.                             Smith, Jr.
8               Unknown

我理想的输出是这样的,首字母正确地分开:

Collector.First.Name1 Collector.Middle1 Collector.Last.Name1
1                  Matt                                  Smith
2                  Matt               L.                 Smith
3                  Matt            Louis                 Smith
4                    M.                                  Smith
5                    M.               L.                 Smith
6                    M.               L.            Smith, Jr.
7                    M.                             Smith, Jr.
8               Unknown

使用R 4.2.2

t98cgbkg

t98cgbkg1#

另一种解决方案使用来自tidyrextract;基本上是一行代码:

library(tidyr)
df1 %>%
  extract(name,
          into = c("first", "middle", "last"),
          regex = "(\\w+\\.?)\\s*(?:([^\\s,]+)\\s)?(?:(\\w+(?:,\\sJr\\.)?))?")
    first middle       last
1    Matt             Smith
2    Matt     L.      Smith
3    Matt  Louis      Smith
4      M.             Smith
5      M.     L.      Smith
6      M.     L. Smith, Jr.
7      M.        Smith, Jr.
8 Unknown
qf9go6mv

qf9go6mv2#

使用Gregor的注解解决了这个问题-包括一个预处理步骤,在任何点后面插入一个空格,然后是一个非空格

df2 <- df1 %>%
  mutate(name = gsub(pattern = "(\\.)([^ ])","\\1 \\2", name))

names <- df2 %>%
  mutate(name = gsub('([A-Za-z\\.?]+) ([A-Za-z\\.]+ )?([A-Za-z]+)?', '\\1=\\2=\\3', name)) %>%
  separate(name, c("Collector.First.Name1", "Collector.Middle1", "Collector.Last.Name1"), "=")

Collector.First.Name1 Collector.Middle1 Collector.Last.Name1
1                  Matt                                  Smith
2                  Matt               L.                 Smith
3                  Matt            Louis                 Smith
4                    M.                                  Smith
5                    M.               L.                 Smith
6                    M.               L.            Smith, Jr.
7                    M.                             Smith, Jr.
8               Unknown

相关问题