Разбор по номеру и перемещение номера в существующий столбец в R - PullRequest
0 голосов
/ 18 июня 2020

У меня есть грязные тестовые данные, и я хочу их исправить. Ниже приведен пример соответствующих столбцов, с которыми я работаю:

    df1 <- data.frame(Test_Name = c("Super Test", "Amazing Test", "57 Amazing Test", "Super Test",
 "Excellent Test", "Multiple Combined Tests (22, 23, 24)", "2431 Super Test"), Test_Number = 
c(2431,57,NA,2431,123,NA,NA))

В идеале я хотел бы вытащить числа, которые находятся в столбце Test_Name, и переместить их в столбец Test_Number. В идеале это выглядело бы так:

    ideal <- data.frame(Test_Name = c("Super Test", "Amazing Test", "Amazing Test", "Super Test",
 "Excellent Test", "Multiple Combined Tests (22, 23, 24)", "Super Test"), Test_Number = 
c(2431,57,57,2431,123,NA,2431))

Я не уверен, как разобрать только число в начале, не разбирая каждое слово. Количество слов для каждого теста также различается, поэтому количество столбцов в нем разное. Кроме того, после анализа я не уверен, как бы объединить столбец со столбцом Test_Number, не влияя на то, что в данный момент находится в этом столбце. Любая помощь будет принята с благодарностью!

Заранее спасибо!

Ответы [ 3 ]

1 голос
/ 18 июня 2020

Решение с использованием tidyverse

df2 <- df1 %>%
    mutate(Test_Number = case_when(
        str_detect(Test_Name,"^[0-9]{1,10}") ~ str_extract(Test_Name,"^[0-9]{1,10}"),
        TRUE ~ Test_Number
    ))
df2

Решение использует case_when, чтобы определить, начинается ли строка в Test name с цифр. Если да, извлекает строку, иначе сохраняет значение.

1 голос
/ 18 июня 2020

Решение Tidyverse:

library(tidyverse)
df1 %>% 
  mutate(Test_Number = if_else(is.na(Test_Number), 
                               as.numeric(str_extract(Test_Name, "^[0-9]*")), 
                               Test_Number))

                             Test_Name Test_Number
1                           Super Test        2431
2                         Amazing Test          57
3                      57 Amazing Test          57
4                           Super Test        2431
5                       Excellent Test         123
6 Multiple Combined Tests (22, 23, 24)          NA
7                      2431 Super Test        2431
1 голос
/ 18 июня 2020

Попробуйте следующее:

nums <- regmatches(df1$Test_Name, gregexpr("\\d+", df1$Test_Name))
nums <- unlist(replace(nums, sapply(nums, length) != 1L, NA_character_))
nums
# [1] NA     NA     "57"   NA     NA     NA     "2431"
df1$Test_Number2 <- ifelse(is.na(nums), df1$Test_Number, nums)
df1
#                              Test_Name Test_Number Test_Number2
# 1                           Super Test        2431         2431
# 2                         Amazing Test          57           57
# 3                      57 Amazing Test          NA           57
# 4                           Super Test        2431         2431
# 5                       Excellent Test         123          123
# 6 Multiple Combined Tests (22, 23, 24)          NA           NA
# 7                      2431 Super Test          NA         2431

Я предполагаю, что «длина 1» является важным предикатом для вас, поскольку вы избегали (22,23,24).

Если у вас есть «реальный» NA значений (не буквальных строк "NA"), тогда более безопасная альтернатива может быть:

ifelse(is.na(df1$Test_Number), nums, df1$Test_Number)
...