【问题标题】:How to combine columns based on other columns in r [duplicate]如何根据r中的其他列组合列[重复]
【发布时间】:2020-01-27 11:17:38
【问题描述】:

我想合并产品和价格列,以便复制国家和日期列中的数据。

我的数据:

df1 = data.frame(country = c("USA", "USA", "ITALY"), date = c("10/19", "10/19" , "11/19"),
                 product=c("A","B","A"), price=c( 100, 200, 150), product2 =c("B","A", NA), 
                 price2 = c( 50, 100,NA),product3 =c("B","A", "C"), price3 = c(30,NA,10) )

> df1
  country  date product price product2 price2 product3 price3
1     USA 10/19       A   100        B     50        B     30
2     USA 10/19       B   200        A    100        A     NA
3   ITALY 11/19       A   150     <NA>     NA        C     10

I expected:

 country  date product price
1     USA 10/19       A   100
2     USA 10/19       B   200
3   ITALY 11/19       A   150
4     USA 10/19       B    50
5     USA 10/19       A   100
6     USA 10/19       B    30
7     USA 10/19       A    NA
8   ITALY 11/19       C    10

【问题讨论】:

    标签: r dataframe


    【解决方案1】:

    你可以使用tidyr中的pivot_longer

    library(dplyr)
    library(tidyr)
    
    pivot_longer(df1, 
                  cols = -c(country, date), 
                  names_to = c(".value", "num"), 
                  names_sep = "\\d") %>%
     select(-num) %>%
     na.omit
    
    # A tibble: 5 x 4
    #  country date  product price
    #  <fct>   <fct> <fct>   <dbl>
    #1 USA     10/19 A         100
    #2 USA     10/19 B          50
    #3 USA     10/19 B         200
    #4 USA     10/19 A         100
    #5 ITALY   11/19 A         150
    

    【讨论】:

    • 在我的数据中有很多列包含产品和价格。我正在尝试使用您的代码并收到一条消息:警告消息:预期 2 件。额外的碎片被丢弃在 15 行中
    • @Zizou 是的,那是因为product 列前面没有像product2 这样的数字,所以忽略警告是安全的。它会给你预期的输出吗?
    • 您可以通过更详细一点并将names_sep = "\\d" 更改为names_pattern = '(\\w)($|\\d)' 来避免警告
    • 我在数据中添加了下一列。
    • 好的,但我不想跳过上面例子中看到的所有 NA
    【解决方案2】:

    这个问题和你有关:enter link description here

    以下是您的问题的几个解决方案:

    简单的一个:

    bind_rows(
      df1 %>% select(country, date, product = product, price = price),
      df1 %>% select(country, date, product = product2, price = price2)
    ) %>%
      na.omit()
    

    更具可扩展性:

    nm1 <- names(df1)[-(1:2)] 
    split(nm1, sub("\\D+", "", nm1)) %>% 
      purrr::map_df(~ df1 %>% select(country, date, .x) %>%
               rename_at(3:4, ~ c("product", "price"))) %>%
      na.omit()
    

    对于您编辑的问题:

    library(dplyr)
    library(purrr)
    df1 = data.frame(country = c("USA", "USA", "ITALY"), date = c("10/19", "10/19" , "11/19"),
                     product=c("A","B","A"), price=c( 100, 200, 150), product2 =c("B","A", NA), 
                     price2 = c( 50, 100,NA),product3 =c("B","A", "C"), price3 = c(30,NA,10), stringsAsFactors = FALSE)
    
    nm1 <- names(df1)[-(1:2)] 
    split(nm1, sub("\\D+", "", nm1)) %>% 
      purrr::map_df(~ df1 %>% select(country, date, .x) %>%
                      rename_at(3:4, ~ c("product", "price"))) %>%
      filter(!is.na(product))
    

    结果:

         country  date product price
    1     USA 10/19       A   100
    2     USA 10/19       B   200
    3   ITALY 11/19       A   150
    4     USA 10/19       B    50
    5     USA 10/19       A   100
    6     USA 10/19       B    30
    7     USA 10/19       A    NA
    8   ITALY 11/19       C    10
    

    【讨论】:

    • 我有 factor 和 num 类型,我得到错误:只有字符串可以转换为符号。
    • 创建数据框时,使用选项 stringsAsFactors = FALSE。
    • 我添加了你的解决方案,但我仍然有同样的错误。
    • 我更新了答案,但它应该可以工作。我执行了它,结果就是你想要的。尝试每行执行。
    猜你喜欢
    • 2021-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-08
    • 1970-01-01
    • 1970-01-01
    • 2022-11-11
    • 2022-10-13
    相关资源
    最近更新 更多