pivot_longer 函数在多个类别下出现错误(“无共同类型”)

24

我正在对多列运行pivot_longer(即两个字符列和一个数字列)。我遇到了与类不匹配相关的错误。

我查看了文档,没有发现任何“强制”选项,在pivot_longer中指定要使用的类别,或允许函数自动检测最通用的类别的参数。

有没有pivot_longer内部的参数可以避免此错误?还是需要在运行pivot_longer之前将列转换为单个类别?

library(dplyr)
library(tidyr)
library(ggplot2) # Just for `diamonds` dataset

small_diamonds <- diamonds %>% 
  # Select a few columns (two character, one numeric, specifically integers)
  select(cut, color, price) %>% 
  # Create a row_id
  mutate(row_num = row_number()) 

# This works with `gather`
small_diamonds %>% 
  gather(key, val, - row_num)

# This fails due to class error:
small_diamonds %>% 
  # Pivot data
  pivot_longer( - row_num, 
                names_to = "key",
                values_to = "val")

# Output
# Error: No common type for `cut` <ordered<4bd7e>> and `price` <integer>.
# Call `rlang::last_error()` to see a backtrace

# Convert columns to a single class (character) and then use `pivot_longer`. 
# Runs successfully
small_diamonds %>% 
  mutate_all(as.character) %>% 
  # Pivot data
  pivot_longer( - row_num, 
                names_to = "key",
                values_to = "val")

3个回答

29

当使用values_ptypes参数时,错误以不同的形式再次出现。

library(tidyverse)

small_diamonds <- diamonds %>% 
  select(cut, color, price) %>% 
  mutate(row_num = row_number())

small_diamonds %>%  
  pivot_longer( - row_num, 
                names_to = "key",
                values_to = "val", 
                values_ptypes = list(val = 'character'))
#> Error: Can't convert <integer> to <character>.

因此,我需要使用values_transform参数来获得所需的结果。
library(tidyverse)

  small_diamonds <- diamonds %>% 
    select(cut, color, price) %>% 
    mutate(row_num = row_number())
  
  small_diamonds %>%  
    pivot_longer( - row_num, 
                  names_to = "key",
                  values_to = "val", 
                  values_transform = list(val = as.character))
#> # A tibble: 161,820 x 3
#>    row_num key   val    
#>      <int> <chr> <chr>  
#>  1       1 cut   Ideal  
#>  2       1 color E      
#>  3       1 price 326    
#>  4       2 cut   Premium
#>  5       2 color E      
#>  6       2 price 326    
#>  7       3 cut   Good   
#>  8       3 color E      
#>  9       3 price 327    
#> 10       4 cut   Premium
#> # ... with 161,810 more rows

本示例由 reprex package (v0.3.0) 创建于2020年08月25日


我认为出现这个错误的原因是tidyverse团队希望在数据透视时进行数据类型转换时要显式地进行。 - Koray
为什么这段代码在 relig_income 数据集上无法运行?relig_income %>% pivot_longer(1:11, names_to = "a", values_to = "b", values_transform = list(val = as.character)) - Dario Lacan
1
@DarioLacan 当你正确指定值列的列名时,它就能正常工作。在你的代码中,值列的列名被指定为 val,但是你的值列实际上被命名为 b,当我将 val 替换为 b 时,转换在我的机器上可以正常工作。 - Koray

18
我们可以在这种情况下指定values_ptype(因为值列的类型不同)。
library(ggplot2)
library(tidyr)
library(dplyr)
small_diamonds %>%  
   pivot_longer( - row_num, 
             names_to = "key",
             values_to = "val", values_ptypes = list(val = 'character'))
# A tibble: 161,820 x 3
#   row_num key   val    
#     <int> <chr> <chr>  
# 1       1 cut   Ideal  
# 2       1 color E      
# 3       1 price 326    
# 4       2 cut   Premium
# 5       2 color E      
# 6       2 price 326    
# 7       3 cut   Good   
# 8       3 color E      
# 9       3 price 327    
#10       4 cut   Premium
# … with 161,810 more rows

8
使用你的示例,可以看到使用 str() 可以发现你有两个向量被编码为因子(factor),而另外两个则是整型。pivot_longer 要求所有向量都是相同类型,并且会抛出你所报告的错误。
    library(tidyverse)
    small_diamonds <- diamonds %>%
      select(cut, color, price) %>%
      mutate(row_num = row_number())

    str(small_diamonds)

一个解决方案是使用mutate_if将所有向量转换为字符,然后传递pivot_longer命令。
    small_diamonds %>% 
      mutate_if(is.numeric,as.character, is.factor, as.character) %>% 
      pivot_longer( - row_num, 
            names_to = "key",
            values_to = "val") 

1
我认为在运行 pivot_longer 之前转换列会产生更清晰和易于理解的代码。当使用命令“mutate”时,进行转换非常明显。它还遵循 Unix 的“kiss”原则:使用一个工具转换数据,使用另一个工具“pivot”数据。 - BMLopes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接