【问题标题】:Wide a dataframe and insert missing columns加宽数据框并插入缺失的列
【发布时间】:2021-10-23 06:53:02
【问题描述】:

编辑:dput() 格式添加了更多数据。

我有以下产品数据框,column 的模式为 promo、marca、descripción、cantidad、precio。有时促销会丢失。

我需要更广泛形式的数据框(例如 pivot_wider),但在找不到列的地方插入 NA 值。

 # A tibble: 18 x 2
   text                                              column     
   <chr>                                             <chr>      
 1 2 X$39.990Ahorro:$14.990                          promo      
 2 Pampers                                           marca      
 3 Pañales Desechables Premium Care XXG 112 Unidades descripción
 4 112 Un                                            cantidad   
 5 $27.490                                           precio     
 6 2 X$39.990Ahorro:$14.990                          promo      
 7 Pampers                                           marca      
 8 Pañales Desechables Premium Care XG 112 Unidades  descripción
 9 112 Un                                            cantidad   
10 $27.490                                           precio     
11 Babysec                                           marca      
12 Toalla Húmeda Premium X 140/6                     descripción
13 1 Un                                              cantidad   
14 $2.590                                            precio     
15 Emuwipes                                          marca      
16 Toallitas Húmedas Premium 85 Un c/u Bolsa         descripción
17 2 Un                                              cantidad   
18 $2.650                                            precio    

这是df %&gt;% mutate(id = row_number()) %&gt;% pivot_wider(...) 的输出。有没有办法缩小这个输出?

# A tibble: 18 x 6
      id promo               marca    descripción                            cantidad precio
   <int> <chr>               <chr>    <chr>                                  <chr>    <chr> 
 1     1 2 X$39.990Ahorro:$~ NA       NA                                     NA       NA    
 2     2 NA                  Pampers  NA                                     NA       NA    
 3     3 NA                  NA       Pañales Desechables Premium Care XXG ~ NA       NA    
 4     4 NA                  NA       NA                                     112 Un   NA    
 5     5 NA                  NA       NA                                     NA       $27.4~
 6     6 2 X$39.990Ahorro:$~ NA       NA                                     NA       NA    
 7     7 NA                  Pampers  NA                                     NA       NA    
 8     8 NA                  NA       Pañales Desechables Premium Care XG 1~ NA       NA    
 9     9 NA                  NA       NA                                     112 Un   NA    
10    10 NA                  NA       NA                                     NA       $27.4~
11    11 NA                  Babysec  NA                                     NA       NA    
12    12 NA                  NA       Toalla Húmeda Premium X 140/6          NA       NA    
13    13 NA                  NA       NA                                     1 Un     NA    
14    14 NA                  NA       NA                                     NA       $2.590
15    15 NA                  Emuwipes NA                                     NA       NA    
16    16 NA                  NA       Toallitas Húmedas Premium 85 Un c/u B~ NA       NA    
17    17 NA                  NA       NA                                     2 Un     NA    
18    18 NA                  NA       NA                                     NA       $2.650

数据:

text = c("2 X$39.990Ahorro:$14.990", "Pampers", 
"Pañales Desechables Premium Care XXG 112 Unidades", "112 Un", 
"$27.490", "2 X$39.990Ahorro:$14.990", "Pampers", "Pañales Desechables Premium Care XG 112 Unidades", 
"112 Un", "$27.490", "Babysec", "Toalla Húmeda Premium X 140/6", 
"1 Un", "$2.590", "Emuwipes", "Toallitas Húmedas Premium 85 Un c/u Bolsa", 
"2 Un", "$2.650", "Parent's Choice", "Toallitas Húmedas Ultra Soft con Aceite de Emu 160 Un", 
"160 Un", "$2.550", "Emuwipes", "Toallitas Húmedas sin Alcohol (2 Bolsas de 80 Un c/u) Bolsa 2 Un", 
"$1.990", "3 X$45.990Ahorro:$13.980", "Babysec", "Pañal Super Premium XXG68", 
"1 Un", "$19.990", "Parent's Choice", "Toallitas Húmedas Ultra Soft con Aceite de Emu y sin Aroma (2 Un de 80 Un c/u)", 
"160 Un", "$2.550", "2 X$39.990Ahorro:$14.990", "Pampers", "Pañales Desechables Premium Care G 124 Unidades", 
"124 Un", "$27.490", "Huggies")

column = c("promo", "marca", 
"descripción", "cantidad", "precio", "promo", "marca", "descripción", 
"cantidad", "precio", "marca", "descripción", "cantidad", "precio", 
"marca", "descripción", "cantidad", "precio", "marca", "descripción", 
"cantidad", "precio", "marca", "descripción", "precio", "promo", 
"marca", "descripción", "cantidad", "precio", "marca", "descripción", 
"cantidad", "precio", "promo", "marca", "descripción", "cantidad", 
"precio", "marca")

【问题讨论】:

  • 顺便说一句,将您的数据包含在可重现的格式中会很有帮助,例如通过包含dput(df) 的输出,这样我们就可以运行代码而无需进行大量重新格式化以重新创建您的df
  • 为了扩大你的数据框,函数必须知道哪些行属于一起(函数不关心行顺序)。在您的操作中,您使用索引作为(有效)分组标识符,因此每个条目都有自己的行(所有其他条目都有 NA)。如果您添加一个分组列,并将该列用作 id 的参数,那应该可以解决您的问题。
  • 谢谢@JonSpring,我不知道。对于第二条评论,我不知道如何获取分组列。

标签: r dplyr tidyverse tidyr data-manipulation


【解决方案1】:

更新: OP 和其他人使用新提供的数据和此处获得的知识提出的问题:Recognize a given pattern in a vector and add the lacking elements to get the repitition of the given pattern

library(tidyverse)
df1 %>% 
    group_by(column) %>% 
    mutate(row = row_number()) %>%
    pivot_wider(
        names_from = column,
        values_from = text
    )

给予:

     row promo                    marca           descripción                                                                    cantidad precio 
   <int> <chr>                    <chr>           <chr>                                                                          <chr>    <chr>  
 1     1 2 X$39.990Ahorro:$14.990 Pampers         Pañales Desechables Premium Care XXG 112 Unidades                              112 Un   $27.490
 2     2 2 X$39.990Ahorro:$14.990 Pampers         Pañales Desechables Premium Care XG 112 Unidades                               112 Un   $27.490
 3     3 3 X$45.990Ahorro:$13.980 Babysec         Toalla Húmeda Premium X 140/6                                                  1 Un     $2.590 
 4     4 2 X$39.990Ahorro:$14.990 Emuwipes        Toallitas Húmedas Premium 85 Un c/u Bolsa                                      2 Un     $2.650 
 5     5 NA                       Parent's Choice Toallitas Húmedas Ultra Soft con Aceite de Emu 160 Un                          160 Un   $2.550 
 6     6 NA                       Emuwipes        Toallitas Húmedas sin Alcohol (2 Bolsas de 80 Un c/u) Bolsa 2 Un               1 Un     $1.990 
 7     7 NA                       Babysec         Pañal Super Premium XXG68                                                      160 Un   $19.990
 8     8 NA                       Parent's Choice Toallitas Húmedas Ultra Soft con Aceite de Emu y sin Aroma (2 Un de 80 Un c/u) 124 Un   $2.550 
 9     9 NA                       Pampers         Pañales Desechables Premium Care G 124 Unidades                                NA       $27.490
10    10 NA                       Huggies         NA                                                                             NA       NA     

第一个答案:

我们可以为每个column 创建一个唯一标识符行,然后使用pivot_wider

library(tidyverse)
df %>% 
    group_by(column) %>% 
    mutate(row = row_number()) %>%
    pivot_wider(
        names_from = column,
        values_from = text
    ) 
    row promo                    marca    descripción                                       cantidad precio 
  <int> <chr>                    <chr>    <chr>                                             <chr>    <chr>  
1     1 2 X$39.990Ahorro:$14.990 Pampers  Pañales Desechables Premium Care XXG 112 Unidades 112 Un   $27.490
2     2 2 X$39.990Ahorro:$14.990 Pampers  Pañales Desechables Premium Care XG 112 Unidades  112 Un   $27.490
3     3 NA                       Babysec  Toalla Húmeda Premium X 140/6                     1 Un     $2.590 
4     4 NA                       Emuwipes Toallitas Húmedas Premium 85 Un c/u Bolsa         2 Un     $2.650

【讨论】:

  • 无论如何你都不要担心。我仍然投票给答案,因为 OP 确实指定 PROMO 是缺少的。如果要拿走一个珍品,其他答案也将失败。所以你的回答是有效的。这个答案是提供的答案中最可靠的答案
  • 这可行,但输出错误,因为将所有 promo 值分组在数据框的上侧。
  • 你的意思是促销的顺序?
  • 当代码没有找到促销时,将后续值向上移动。错误显示在我上传的新数据中。
  • 我认为这种方法更“稳健”是一种责任——即使输出错误,它也会提供输出,而当构成分组的基本假设失败时,其他方法将失败.
【解决方案2】:

如果每个项目都有一个precio,我们可以使用下面的代码,计算在前面的行中出现了多少precio 条目。 lag(column, default = "") 用于避免第一项出现“NA”,这会破坏累积计数。

df %>%
  mutate(row = cumsum(lag(column, default = "") == "precio")) %>% 
  pivot_wider(names_from = column, values_from = text)


# A tibble: 4 x 6
    row promo                    marca    descripción                                       cantidad precio 
  <int> <chr>                    <chr>    <chr>                                             <chr>    <chr>  
1     0 2 X$39.990Ahorro:$14.990 Pampers  Pañales Desechables Premium Care XXG 112 Unidades 112 Un   $27.490
2     1 2 X$39.990Ahorro:$14.990 Pampers  Pañales Desechables Premium Care XG 112 Unidades  112 Un   $27.490
3     2 NA                       Babysec  Toalla Húmeda Premium X 140/6                     1 Un     $2.590 
4     3 NA                       Emuwipes Toallitas Húmedas Premium 85 Un c/u Bolsa         2 Un     $2.650 

编辑:使用marca 的替代方法,但promo 被分配给下一个分组(因为它假定总是在marca 出现时出现)。样本数据的输出相同。

df %>%
  mutate(row = cumsum(column == "marca") + if_else(column == "promo", 1, 0)) %>%
  pivot_wider(names_from = column, values_from = text)

源数据

df <- data.frame(
  stringsAsFactors = FALSE,
                    text = c("2 X$39.990Ahorro:$14.990","Pampers",
                             "Pañales Desechables Premium Care XXG 112 Unidades","112 Un","$27.490",
                             "2 X$39.990Ahorro:$14.990","Pampers",
                             "Pañales Desechables Premium Care XG 112 Unidades","112 Un","$27.490",
                             "Babysec","Toalla Húmeda Premium X 140/6",
                             "1 Un","$2.590","Emuwipes",
                             "Toallitas Húmedas Premium 85 Un c/u Bolsa","2 Un","$2.650"),
                  column = c("promo","marca",
                             "descripción","cantidad","precio","promo",
                             "marca","descripción","cantidad","precio","marca",
                             "descripción","cantidad","precio","marca",
                             "descripción","cantidad","precio")
      )

【讨论】:

  • 正是我的想法,但没有设法编写代码。您将如何修补它以使用 marca 而不是 precio
  • 添加了一个基于 marca 的替代方案。由于promo,当它出现时,出现在marca之前,我将它们转移到下一个分组。
【解决方案3】:

使用来自data.tabledcast。将'data.frame'转换为'data.table'(setDT),创建一个累积和的公式(基于取'column'(shift)的lag,检查值是否等于'precio',用'column'获取累积和(cumsum),并在dcast中将value.var指定为'text'以从'long'格式重塑为'wide'格式

library(data.table)
 dcast(setDT(df), cumsum(shift(column, fill = "") == "precio" )~ column, value.var = 'text')

【讨论】:

  • cumsumshift 组合的绝妙技巧。我可以看到它的作用,但是添加几句话来说明究竟发生了什么以及为什么它在这种情况下有效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-17
  • 1970-01-01
  • 2015-07-01
相关资源
最近更新 更多