从R中的单个列中提取多个变量

从R中的单个列中提取多个变量,r,dplyr,tidyr,R,Dplyr,Tidyr,我正在处理一个数据清理问题,我被卡住了。我已经开始接收以下格式的csv文件,我需要先清理它,然后才能进行任何分析。有几个这样的列,每个单元格中可能有几百个需要提取的变量 Original <- structure(list(CustNum = c(0, 1), Sales = c("[1000, 345, Zero, 56]", "[987, 879, 325, 4568]"),

我正在处理一个数据清理问题,我被卡住了。我已经开始接收以下格式的csv文件,我需要先清理它,然后才能进行任何分析。有几个这样的列,每个单元格中可能有几百个需要提取的变量

Original <- structure(list(CustNum = c(0, 1),
                      Sales = c("[1000, 345, Zero, 56]", "[987, 879, 325, 4568]"),
                      Amounts = c("[10, 2, 0, 98]", "[57, 25, 52, 75]"),
                      Number = c("['1', '2', '3', '4']", "['4', '3', '2', '1']"),
                      Identifier = c("A", "B")),
                      row.names = c(NA, -2L),
                      class = c("tbl_df", "tbl", "data.frame"))

在Excel中的Power Query中进行清理很容易,但我想找到一种在R中进行清理的方法,这样我就不必使用多种不同的工具。有人能告诉我怎么做吗?

我建议采用这种方法,首先将
原始的
数据重塑为长数据,然后按
sep=','分隔行。之后,您将清理变量以删除一些特殊字符。因此,您可以按组创建id变量,以便在
所需的
中将数据转换为所需的宽度:

library(tidyverse)
#Reshape
Original %>%
  pivot_longer(cols = -c(CustNum,Identifier)) %>%
  separate_rows(value,sep = ',') %>%
  mutate(value=trimws(gsub("[[:punct:]]", " ", value))) %>%
  group_by(name) %>% mutate(id=1:n()) %>%
  pivot_wider(names_from = name,values_from=value) %>% 
  ungroup() %>%
  select(-id)
输出:

# A tibble: 8 x 5
  CustNum Identifier Sales Amounts Number
    <dbl> <chr>      <chr> <chr>   <chr> 
1       0 A          1000  10      1     
2       0 A          345   2       2     
3       0 A          Zero  0       3     
4       0 A          56    98      4     
5       1 B          987   57      4     
6       1 B          879   25      3     
7       1 B          325   52      2     
8       1 B          4568  75      1  
#一个tible:8 x 5
CustNum标识符销售金额编号
10 A 1000 10 1
20A34522
30A03
40A 5698 4
51B987574
61B879253
7 1 B 325 52 2
81B4568751

我建议采用这种方法,首先将
原始
数据重塑为long,然后通过
sep=','
分隔行。之后,您将清理变量以删除一些特殊字符。因此,您可以按组创建id变量,以便在
所需的
中将数据转换为所需的宽度:

library(tidyverse)
#Reshape
Original %>%
  pivot_longer(cols = -c(CustNum,Identifier)) %>%
  separate_rows(value,sep = ',') %>%
  mutate(value=trimws(gsub("[[:punct:]]", " ", value))) %>%
  group_by(name) %>% mutate(id=1:n()) %>%
  pivot_wider(names_from = name,values_from=value) %>% 
  ungroup() %>%
  select(-id)
输出:

# A tibble: 8 x 5
  CustNum Identifier Sales Amounts Number
    <dbl> <chr>      <chr> <chr>   <chr> 
1       0 A          1000  10      1     
2       0 A          345   2       2     
3       0 A          Zero  0       3     
4       0 A          56    98      4     
5       1 B          987   57      4     
6       1 B          879   25      3     
7       1 B          325   52      2     
8       1 B          4568  75      1  
#一个tible:8 x 5
CustNum标识符销售金额编号
10 A 1000 10 1
20A34522
30A03
40A 5698 4
51B987574
61B879253
7 1 B 325 52 2
81B4568751
试试这个:

library(dplyr) # must be version >= 1.0.0
library(stringr)

Original %>%
 mutate(across(everything(), str_remove_all, pattern = "\\[|\\]|\\'")) %>% 
 mutate(across(everything(), str_split, pattern = ",")) %>%                
 tidyr::unnest(everything()) %>% 
 mutate(across(everything(), str_trim)) %>% 
 mutate(across(c(CustNum, Amounts, Number), as.numeric))
#一个tible:8 x 5
CustNum销售金额编号标识符
101000101A
23034522A
30003A
4056984A
51987574B
61879253B
71325522B
814568751B
基本上:

  • 删除
    [
    ]
    '
  • 取消列表
  • 修剪掉不必要的空间
  • 必要时设置为数字
试试这个:

library(dplyr) # must be version >= 1.0.0
library(stringr)

Original %>%
 mutate(across(everything(), str_remove_all, pattern = "\\[|\\]|\\'")) %>% 
 mutate(across(everything(), str_split, pattern = ",")) %>%                
 tidyr::unnest(everything()) %>% 
 mutate(across(everything(), str_trim)) %>% 
 mutate(across(c(CustNum, Amounts, Number), as.numeric))
#一个tible:8 x 5
CustNum销售金额编号标识符
101000101A
23034522A
30003A
4056984A
51987574B
61879253B
71325522B
814568751B
基本上:

  • 删除
    [
    ]
    '
  • 取消列表
  • 修剪掉不必要的空间
  • 必要时设置为数字

    • 您可以尝试这种方法

      library(tidyverse)
      library(stringr)
      Original2 <- Original %>% 
        mutate_at(vars(Sales, Amounts, Number), ~str_replace_all(., "\\[|\\'|\\]|\\s", "")) %>% 
        separate_rows(c("Sales", "Amounts", "Number"), sep = ",")
      
      #   CustNum Sales Amounts Number Identifier
      #     <dbl> <chr> <chr>   <chr>  <chr>     
      # 1       0 1000  10      1      A         
      # 2       0 345   2       2      A         
      # 3       0 Zero  0       3      A         
      # 4       0 56    98      4      A         
      # 5       1 987   57      4      B         
      # 6       1 879   25      3      B         
      # 7       1 325   52      2      B         
      # 8       1 4568  75      1      B  
      
      库(tidyverse)
      图书馆(stringr)
      原始2%
      在(变量(销售额、金额、数量)处进行变异,~str\u替换所有(,“\\[\\\'\\\\]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
      单独的行(c(“销售额”、“金额”、“数量”),sep=“,”)
      #CustNum销售金额编号标识符
      #                 
      #101000101A
      #23034522A
      #30003A
      #4056984A
      #51987574B
      #61879253B
      #71325522B
      #814568751B
      

      这里我们替换[,”和空格,然后使用
      separate_rows()
      from
      tidyr
      包来分隔行。实现我们的目标需要两个步骤。

      您可以尝试这种方法

      library(tidyverse)
      library(stringr)
      Original2 <- Original %>% 
        mutate_at(vars(Sales, Amounts, Number), ~str_replace_all(., "\\[|\\'|\\]|\\s", "")) %>% 
        separate_rows(c("Sales", "Amounts", "Number"), sep = ",")
      
      #   CustNum Sales Amounts Number Identifier
      #     <dbl> <chr> <chr>   <chr>  <chr>     
      # 1       0 1000  10      1      A         
      # 2       0 345   2       2      A         
      # 3       0 Zero  0       3      A         
      # 4       0 56    98      4      A         
      # 5       1 987   57      4      B         
      # 6       1 879   25      3      B         
      # 7       1 325   52      2      B         
      # 8       1 4568  75      1      B  
      
      库(tidyverse)
      图书馆(stringr)
      原始2%
      在(变量(销售额、金额、数量)处进行变异,~str\u替换所有(,“\\[\\\'\\\\]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
      单独的行(c(“销售额”、“金额”、“数量”),sep=“,”)
      #CustNum销售金额编号标识符
      #                 
      #101000101A
      #23034522A
      #30003A
      #4056984A
      #51987574B
      #61879253B
      #71325522B
      #814568751B
      

      在这里,我们替换[,”和空格,然后使用
      separate_rows()
      from
      tidyr
      包来分隔行。实现我们的目标需要两个步骤。

      这是一个非常酷的解决方案!!做得很好!但是,我认为您应该使用
      mutate(跨(…)来更改
      mutate_at(…)
      因为它现在被取代了。比如:
      变异(跨越(c)(销售额、金额、数字),str\u删除所有,\\[\\\\\\\]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\(销售额、金额、数字),str\u remove\u all,“\\[\\\\\\\\\\\\]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\”)%>%