【问题标题】:Creating two new columns and removing the source column创建两个新列并删除源列
【发布时间】:2019-12-08 17:41:17
【问题描述】:

我有以下示例数据:

df <- data.frame(ID=c("A1","A2","A3","A4","A1","A2","A3","A4"),
                 NUM=c(469,586,394,595,398,203,604,809))

我希望提取 NUM 列的第一个值并将其放入新列 NUM1,然后在第二次出现相同 ID 的 NUM 值时,将该值提取到新列 NUM2 中。最后,我想删除原始列。除了 ID 和 NUM 之外,我拥有的数据集还有更多变量和列。以下是所需的输出。

df1 <- data.frame(ID=c("A1","A2","A3","A4"),NUM1=c(469,586,394,595),NUM2=c(398,203,604,809))

【问题讨论】:

    标签: r dataframe


    【解决方案1】:

    这是一种方法。您需要创建一个COL 列作为新列的名称,因此在本例中,我们使用group_bystr_c 来创建此列。 pivot_widerspread 函数的更新版本。所有这些功能都来自tidyverse 包。

    library(tidyverse)
    
    df1 <- df %>%
      group_by(ID) %>%
      mutate(COL = str_c("NUM", row_number())) %>%
      pivot_wider(names_from = COL, values_from = NUM) %>%
      ungroup()
    df1
    # # A tibble: 4 x 3
    #   ID     NUM1  NUM2
    #   <fct> <dbl> <dbl>
    # 1 A1      469   398
    # 2 A2      586   203
    # 3 A3      394   604
    # 4 A4      595   809
    

    【讨论】:

      【解决方案2】:

      使用基础 R 你可以这样做:

       reshape(transform(df,time=cumsum(grepl("1",ID))),idvar = "ID",dir="wide",sep="")
      
        ID NUM1 NUM2
      1 A1  469  398
      2 A2  586  203
      3 A3  394  604
      4 A4  595  809
      

      或者你可以试试:

      `colnames<-`(t(unstack(df,NUM~ID)),c("NUM1","NUM2"))
         NUM1 NUM2
      A1  469  398
      A2  586  203
      A3  394  604
      A4  595  809
      

      【讨论】:

        【解决方案3】:

        @akrun 雄辩的 Base R 解决方案:

        df1 <- aggregate(NUM ~ ID, df, I)
        

        (我的)Base R 解决方案:

        #Transform the dataframe: 
        
        df1 <- within(df, {
                      count_num_by_id <- ave(NUM, ID, FUN = seq.int);
                      NUM2 <- ifelse(count_num_by_id == 2, NUM, 0);
                      NUM <- ifelse(count_num_by_id == 1, NUM, 0);
                      rm(count_num_by_id)})
        
        # Aggregate the dataframe: 
        
        df1 <- data.frame(aggregate(.~ID, df1, sum))
        

        【讨论】:

        • @akrun 极好的解决方案。我在上面修改了我的。
        【解决方案4】:

        您可以通过子集获取每个ID的第一个和第二个值

        library(dplyr)
        
        df %>%
          group_by(ID) %>%
          summarise(NUM1 = NUM[1L], 
                    NUM2 = NUM[2L])
        
        # A tibble: 4 x 3
        #  ID     NUM1  NUM2
        #  <fct> <dbl> <dbl>
        #1 A1      469   398
        #2 A2      586   203
        #3 A3      394   604
        #4 A4      595   809
        

        如果您要维护其他列,可以使用mutate

        library(dplyr)
        df %>%
          group_by(ID) %>%
          mutate(NUM1 = NUM[1L], 
                 NUM2 = NUM[2L]) %>%
          slice(1L) %>%
          select(-NUM)
        

        【讨论】:

          【解决方案5】:

          data.table 解决方案...

          require(data.table)
          
          # Set as a data.table and create a unique row.
          setDT(df)[, rid := paste0('NUM', rowid(ID))]
          
          # Cast the data by ID and rid.
          df <- dcast(df, ID ~ rid, value.var = 'NUM')
          
          df
          #    ID NUM1 NUM2
          # 1: A1  469  398
          # 2: A2  586  203
          # 3: A3  394  604
          # 4: A4  595  809
          

          【讨论】:

            【解决方案6】:

            这是一个alternativedcast() 方法,它直接在公式中调用rowid(),并且还将处理df 中的其他列:

            library(data.table)
            dcast(setDT(df), ID + ... ~ rowid(ID, prefix = "NUM"), value.var = "NUM")
            
               ID NUM1 NUM2
            1: A1  469  398
            2: A2  586  203
            3: A3  394  604
            4: A4  595  809
            

            注意对rowid() 的调用中的prefix = "NUM" 参数。

            df 中的其他列

            OP 指出他的数据集 [...] 除了 ID 和 NUM 之外,还有更多的变量和列

            如果每个ID 的附加列的值相同,那么+ ... 会将它们添加到输出中:

            df2 <- data.frame(
              ID = c("A1", "A2", "A3", "A4", "A1", "A2", "A3", "A4"),
              NUM = c(469, 586, 394, 595, 398, 203, 604, 809),
              other1 = rep(4:1, 2),
              other2 = rep(letters[1:4], 2)
            )
            
            df2
            
              ID NUM other1 other2
            1 A1 469      4      a
            2 A2 586      3      b
            3 A3 394      2      c
            4 A4 595      1      d
            5 A1 398      4      a
            6 A2 203      3      b
            7 A3 604      2      c
            8 A4 809      1      d
            
            dcast(setDT(df2), ID + ... ~ rowid(ID, prefix = "NUM"), value.var = "NUM")
            
               ID other1 other2 NUM1 NUM2
            1: A1      4      a  469  398
            2: A2      3      b  586  203
            3: A3      2      c  394  604
            4: A4      1      d  595  809
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2020-03-21
              • 1970-01-01
              • 2018-10-31
              • 2021-04-10
              • 1970-01-01
              • 2016-10-14
              • 1970-01-01
              相关资源
              最近更新 更多