如何使用其他列 (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))
我想创建一个 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))