【问题标题】:Using pivot_longer with existing names_to column将 pivot_longer 与现有的 names_to 列一起使用
【发布时间】:2020-10-07 16:30:41
【问题描述】:

以这样的示例数据框为例(真实的数据框有更多列):

df <- data.frame(A = seq(1, 3, 1),
                 B = seq(4, 6, 1))

我可以使用pivot_longer 来收集我感兴趣的列(AB),如下所示:

library(dplyr)
library(tidyr)
df <- df %>% 
  pivot_longer(cols = c("A", "B"), names_to = "Letter", values_to = "Number")
df
  Letter Number
  <chr>   <dbl>
1 A           1
2 B           4
3 A           2
4 B           5
5 A           3
6 B           6

现在假设我的数据框中有另一列 C,使其不再整洁

C <- seq(7, 12, 1)

df_2 <- data.frame(df, C)
df_2
  Letter Number  C
1      A      1  7
2      B      4  8
3      A      2  9
4      B      5 10
5      A      3 11
6      B      6 12

我想再次使用pivot_longer 使df_2 整洁并得到这个输出:

data.frame(Letter = c(rep("A", 3), rep("B", 3), rep("C", 3)),
                        Number = seq(1, 12, 1))
   Letter Number
1       A      1
2       A      2
3       A      3
4       B      4
5       B      5
6       B      6
7       C      7
8       C      8
9       C      9
10      C     10
11      C     11
12      C     12

虽然使用相同的策略会产生错误:

df_2 %>% 
  pivot_longer(cols = "C", names_to = "Letter", values_to = "Number")
Error: Failed to create output due to bad names.
* Choose another strategy with `names_repair`

names_repair 设置为minimal 会运行,但不会产生我想要的输出。

【问题讨论】:

  • 为什么不单独pivot_longerC 然后联合两者
  • @AnilGoyal 如果你把它写下来作为答案,我会给你一个互联网点
  • 请看解决办法

标签: r tidyr


【解决方案1】:

像这样关注它

library(tidyverse)
df <- data.frame(A = seq(1, 3, 1),
                 B = seq(4, 6, 1))
df <- df %>% 
  pivot_longer(cols = c("A", "B"), names_to = "Letter", values_to = "Number")

C <- seq(7, 12, 1)
df_2 <- data.frame(C)
df_2 <- df_2 %>% pivot_longer(cols = C, names_to = "Letter", values_to = "Number")

df_result <- rbind(df, df_2)

输出

> df_result
# A tibble: 12 x 2
   Letter Number
   <chr>   <dbl>
 1 A           1
 2 B           4
 3 A           2
 4 B           5
 5 A           3
 6 B           6
 7 C           7
 8 C           8
 9 C           9
10 C          10
11 C          11
12 C          12

【讨论】:

    【解决方案2】:

    如果有帮助,不妨试试这个:

    library(tidyverse)
    #Code
    df_2 %>% pivot_longer(everything()) %>%
      arrange(name) %>% group_by(name) %>%
      filter(!duplicated(value))
    

    输出:

    # A tibble: 12 x 2
    # Groups:   name [3]
       name  value
       <chr> <dbl>
     1 A         1
     2 A         2
     3 A         3
     4 B         4
     5 B         5
     6 B         6
     7 C         7
     8 C         8
     9 C         9
    10 C        10
    11 C        11
    12 C        12
    

    【讨论】:

    • 您正在排除数据集中存在重复值的可能性
    【解决方案3】:

    我们可以通过stack轻松做到这一点

    library(dplyr)
    stack(df_2)[2:1] %>% 
         distinct %>%
         set_names(c("Letter", "Number"))
    

    -输出

    #    Letter Number
    #1       A      1
    #2       A      2
    #3       A      3
    #4       B      4
    #5       B      5
    #6       B      6
    #7       C      7
    #8       C      8
    #9       C      9
    #10      C     10
    #11      C     11
    #12      C     12
    

    或者unnest/enframe的选项

    library(tidyr)
    library(tibble)
    unclass(df_2) %>% 
         enframe(name = "Letter", value = "Number") %>% 
         unnest(c(Number)) %>% 
         distinct
    

    或者使用melt

    library(reshape2)
    melt(df_2) %>% 
          distinct()
    

    或者在base R中的一行

    unique(stack(df_2)[2:1])
    

    【讨论】:

    • 这些都不适合我。基于stack 的解决方案(1 和4)都给出了一个混合了“字母”、“数字”和“C”的列,以及另一个混合了“A”、“B”和数字1-12 的列。 unclass 解决方案由于类型不匹配而无法运行,melt 解决方案提供了完全不同的东西,一个包含三列、字母、变量和值的数据框
    • @Greg 对我来说,我得到了你所期望的准确输出
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-08
    • 1970-01-01
    • 2019-03-21
    • 1970-01-01
    • 1970-01-01
    • 2013-04-19
    • 1970-01-01
    相关资源
    最近更新 更多