【问题标题】:How can I create a columns with the values in other column (R)?如何使用其他列 (R) 中的值创建列?
【发布时间】:2021-12-25 06:17:04
【问题描述】:

我想创建一个表,为一列的每个值分配一列。

数据如下:


   Person       Task      

   John          4        
   Michael       1           
   Florence      3      


预期结果:

  Person       Task     1     2     3      4     5    6    7    8   

   John          4      1     1     1      1     0    0    0    0  
   Michael       1      0     0     0      0     1    0    0    0     
   Florence      3      0     0     0      0     0    1    1    1

重要的是,列值要按顺序填写。第一行,然后是第二行,以此类推。

谢谢!

【问题讨论】:

  • t(model.matrix(~inverse.rle(setNames(df, c('values', 'lengths'))) - 1))

标签: r datatable pivot-table


【解决方案1】:

diag() 的解决方案,因为添加的值具有对角矩阵的形状,只是重复列:

n <- length(dat$Task)
cbind( dat, matrix( unlist( apply( rbind(as.integer(dat$Task), 1:n), 2, 
  function(x) rep(diag(n)[,x[2]], x[1]) ) ), n ) )

    Person Task 1 2 3 4 5 6 7 8
1     John    4 1 1 1 1 0 0 0 0
2  Michael    1 0 0 0 0 1 0 0 0
3 Florence    3 0 0 0 0 0 1 1 1

数据:

dat <- structure(list(Person = c("John", "Michael", "Florence"), Task = c(4L,
1L, 3L)), class = "data.frame", row.names = c(NA, -3L))

【讨论】:

    【解决方案2】:

    在基础 R 中:

    cbind(df, t(unname(model.matrix(~with(df, factor(rep(Person, Task), Person))-1))))
    
        Person Task 1 2 3 4 5 6 7 8
    1     John    4 1 1 1 1 0 0 0 0
    2  Michael    1 0 0 0 0 1 0 0 0
    3 Florence    3 0 0 0 0 0 1 1 1
    

    为了更简单的代码:

    创建如下所示的数据框:

    df1 <- with(df, data.frame(lengths = Task, values = factor(Person, Person)))
    df1
      lengths   values
    1       4     John
    2       1  Michael
    3       3 Florence
    

    请注意,值现在是一个因子列,其级别与值相同。

    那么你可以这样做:

    cbind(df, t(unname(model.matrix(~inverse.rle(df1)-1))))
        Person Task 1 2 3 4 5 6 7 8
    1     John    4 1 1 1 1 0 0 0 0
    2  Michael    1 0 0 0 0 1 0 0 0
    3 Florence    3 0 0 0 0 0 1 1 1
    

    【讨论】:

      【解决方案3】:

      你可以使用

      library(dplyr)
      library(tidyr)
      
      df %>% 
        uncount(Task, .remove = FALSE) %>% 
        mutate(rn = row_number(),
               value = 1) %>% 
        pivot_wider(c(Person, Task), 
                    names_from = rn, 
                    values_from = value,
                    values_fill = 0)
      

      返回

      # A tibble: 3 x 10
        Person    Task   `1`   `2`   `3`   `4`   `5`   `6`   `7`   `8`
        <chr>    <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
      1 John         4     1     1     1     1     0     0     0     0
      2 Michael      1     0     0     0     0     1     0     0     0
      3 Florence     3     0     0     0     0     0     1     1     1
      

      【讨论】:

        【解决方案4】:

        设置你的数据框:

        > df <- data.frame(Name=factor(c("John", "Michael", "Florence"), levels=c("John", "Michael", "Florence")), Task=c(4,1,3))
        > df
              Name Task
        1     John    4
        2  Michael    1
        3 Florence    3
        

        首先,我将制作一个“长”数据框,将每个名称和任务扩展为所需的条目数。 id 将确保当我重塑数据框宽度时,列具有正确的名称:

        df2 <- data.frame(Name=rep(df$Name, df$Task),
                   Task=rep(df$Task, df$Task),
                   id = 1:sum(df$Task))
        > df2
              Name Task id
        1     John    4  1
        2     John    4  2
        3     John    4  3
        4     John    4  4
        5  Michael    1  5
        6 Florence    3  6
        7 Florence    3  7
        8 Florence    3  8
        

        现在我可以使用 reshape2 中的 dcast 函数进行宽幅整形

        reshape2::dcast(df2, Name+Task ~ id, fun.aggregate = length, value.var="id")
              Name Task 1 2 3 4 5 6 7 8
        1     John    4 1 1 1 1 0 0 0 0
        2  Michael    1 0 0 0 0 1 0 0 0
        3 Florence    3 0 0 0 0 0 1 1 1
        

        【讨论】:

          猜你喜欢
          • 2023-01-24
          • 1970-01-01
          • 2022-12-05
          • 1970-01-01
          • 1970-01-01
          • 2022-07-05
          • 1970-01-01
          • 2023-01-12
          • 1970-01-01
          相关资源
          最近更新 更多