Регулярное выражение Отдельные столбцы Полное имя в Фамилия, Имя Имя Полное имя (или Начальный) Формат - PullRequest
1 голос
/ 20 марта 2020

У меня есть столбец FULLNAME, я хочу разделить его на 3 столбца: LASTNAME, FIRSTNAME, MIDDLE_NAME_INITIAL В приведенный ниже пример включены различные случаи. Я думаю, что мой код легче посмотреть, чем мое описание.

df <- data.frame(FULLNAME = c("John, Smith J.", 
                          "David, Cameron", 
                          "Adam-Steve, Johnson M.", 
                          "Antonio, Zang-Chi K", 
                          "Joan Philippe, Luis Carlos", 
                          "Dave, Jr., Danny Rock",
                          "Jake, Joan-Anberto",
                          "Annie, L.K Selena",
                          "Anna, P. Zhei"))

Вывод:

       LASTNAME    FIRSTNAME MIDDLE_NAME_INITIAL
1          John        Smith             J.
2         David      Cameron               
3    Adam-Steve      Johnson             M.
4       Antonio     Zang-Chi              K
5 Joan Philippe         Luis         Carlos
6     Dave, Jr.        Danny           Rock
7          Jake Joan-Anberto               
8         Annie       Selena            L.K
9          Anna         Zhei             P.

У меня есть вещи Google, и я нашел это здесь I пробовал разные способы, один из них pattern = "(.+),\\s*(.+)\\s+(.+)", но он не смог получить ожидаемый результат. Будем благодарны за каждую рекомендацию.

Ответы [ 3 ]

1 голос
/ 20 марта 2020

Попробуйте это выражение:

([\w\s.,-]+)(?:[^,]*,\s){1,}([\w.-]+)\s*([\w.-]*)

Здесь вы можете увидеть, как это работает: https://regexr.com/50oef

Я не знаю язык R, поэтому позвольте мне показать пример, используя Java:

List<String> items = Arrays.asList(
        "John, Smith J.",
        "David, Cameron",
        "Adam-Steve, Johnson M.",
        "Antonio, Zang-Chi K",
        "Joan Philippe, Luis Carlos",
        "Dave, Jr., Danny Rock",
        "Jake, Joan-Anberto",
        "Annie, L.K Selena",
        "Anna, P. Zhei");

Pattern regex = Pattern.compile("([\\w\\s.,-]+)(?:[^,]*,\\s){1,}([\\w.-]+)\\s*([\\w.-]*)");

int k = 0;
for (String item : items) {
    Matcher m = regex.matcher(item);

    if (m.find()) {
        String group1 = m.group(1);
        String group2 = m.group(2);
        String group3 = m.group(3);

        boolean initialsInGroup2 = group2.contains(".");
        boolean initialsInGroup3 = group3.contains(".");

        System.out.println(++k
                + (!"".equals(group1) ? String.format("%15s", group1) : "")
                + (!"".equals(group2) ? String.format("%15s", initialsInGroup2 ? group3 : group2) : "")
                + (!"".equals(group3) ? String.format("%10s", initialsInGroup3 ? group3 : initialsInGroup2 ? group2 : group3) : ""));
    }
}

Вывод:

1           John          Smith        J.
2          David        Cameron
3     Adam-Steve        Johnson        M.
4        Antonio       Zang-Chi         K
5  Joan Philippe           Luis    Carlos
6      Dave, Jr.          Danny      Rock
7           Jake   Joan-Anberto
8          Annie         Selena       L.K
9           Anna           Zhei        P.
1 голос
/ 20 марта 2020

Поскольку ваши данные не в фиксированном столбцовом порядке, я думаю, что слишком много условных логик c, чтобы попытаться собрать все это в поддерживаемом регулярном выражении в R. Я даже не уверен, как вы могли бы сказать, какие имена являются первыми именами, а какие вторыми, если инициалы не используются, поскольку порядок не является согласованным.

Однако, основываясь на правилах, подразумеваемых тем, как вы анализировали имена вручную, вот некоторый код, который можно копировать эти правила:

extract_initials <- function(x)
{
  y <- lapply(strsplit(x, " "), function(z) z[nzchar(z)])
  sapply(y, function(z){
    if(length(z) == 1) return("")
    else if(!all(grepl("[a-z]", z)))
      return(paste(grep("[a-z]", z, invert = T, value = T), collapse = " "))
    else return(paste(z[length(z)], collapse = " "))
  })
}

extract_first <- function(x)
{
  y <- lapply(strsplit(x, " "), function(z) z[nzchar(z)])
  sapply(y, function(z){
    if(length(z) == 1) return(z)
    else if(!all(grepl("[a-z]", z)))
      return(paste(grep("[a-z]", z, value = T), collapse = " "))
    else return(paste(z[-length(z)], collapse = " "))
  })
}

split_name <- function(x)
{
  partlist <- strsplit(x, ",(?=[^,]*$)", perl = TRUE)
  surnames <- sapply(partlist, `[`, 1)
  forenames <- sapply(partlist, `[`, 2)
  data.frame(surname = surnames, 
             first = extract_first(forenames), 
             middle = extract_initials(forenames),
             stringsAsFactors = FALSE)
}

, и он работает так же просто, как это:

split_name(df$FULLNAME)
#>         surname        first middle
#> 1          John        Smith     J.
#> 2         David      Cameron       
#> 3    Adam-Steve      Johnson     M.
#> 4       Antonio     Zang-Chi      K
#> 5 Joan Philippe         Luis Carlos
#> 6     Dave, Jr.        Danny   Rock
#> 7          Jake Joan-Anberto       
#> 8         Annie       Selena    L.K
#> 9          Anna         Zhei     P.

Создано в 2020-03-20 пакетом prex ( v0.3.0)

1 голос
/ 20 марта 2020

Требуется поддержка регулярных выражений в стиле PCRE. Итак, да ...

/
^                               # start at the beginning of the string
(
  \w+                           # first name
  (?:[- ]\w+)*                  # optional second part of first name
  (?:,(?![^,]*$)\s[\w.]+)?      # optional comma-separated addendum to 1st name
)
,\s                             # delimiting comma and space
(?=                             # assert existence of last name
  .*?                           # bridge gap to last name (pre-initials)
  (\w{2,}(?:-\w{2,})*)          # (optionally multi-part) last name
)
(?=                             # assert existence of optional initials
  (?:.*?\b(\w\.\w\b|\w\b\.?|(?<!-)\w+$))?  # optional initals or middle name
)
/x                              # flag: enable free-spacing mode for expression

См. demo .

Я понятия не имею о R; это всего лишь пример того, как захватить разные части имени, насколько это возможно.

Редактировать : обновлено выражение для обработки дополнительных частей имени, таких как инициалы отчества.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...