如何使用其他列 (R) 中的值创建列?

How can I create a columns with the values in other column (R)?

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

数据如下所示:


   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

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

谢谢!

正在设置您的数据框:

> 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

首先,我将制作一个 'long' 数据框,根据需要的条目数扩展每个名称和任务。 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

你可以使用

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)

这个returns

# 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

在基数 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

具有 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))