我想更新数据框以添加 10 列,其中包含基于另一列的值
从这里开始
df <- data.frame(ID = 1:3, name = c("Bob", "Jim", "Fred"), endValue= c(3, 7, 4))
以这个结尾
|ID|Name|endValue|A|B|C|D|E|F|G|H|I|J|
|1|Bob|3|Y|Y|Y|N|N|N|N|N|N|N|
|2|Jim|7|Y|Y|Y|Y|Y|Y|Y|N|N|N|
|3|Fred|4|Y|Y|Y|Y|N|N|N|N|N|N|
所以每条新记录都需要:
欢迎任何帮助...
答案 0 :(得分:3)
一种选择是通过list
为 'endValue' 列的每个值分别加上 'Y'、'N' 来创建一个 rep
列,其差值是 10,然后是 unnest
把它放宽
library(dplyr)
library(purrr)
library(tidyr)
df %>%
mutate(new = map(endValue, ~ rep(c("Y", "N"), c(.x, 10 - .x)))) %>%
unnest_wider(new) %>%
rename_at(vars(starts_with('..')), ~ LETTERS[1:10])
-输出
# A tibble: 3 x 13
# ID name endValue A B C D E F G H I J
# <int> <chr> <dbl> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
#1 1 Bob 3 Y Y Y N N N N N N N
#2 2 Jim 7 Y Y Y Y Y Y Y N N N
#3 3 Fred 4 Y Y Y Y N N N N N N
或使用 separate
library(stringr)
df %>%
mutate(new = str_c(strrep('Y', endValue),
strrep('N', 10 - endValue))) %>%
separate(new, into = LETTERS[1:10], sep="(?<=[A-Z])(?=[A-Z])")
答案 1 :(得分:2)
同时使用 tidyverse
family with pmap
& pivot_wider
library(dplyr)
library(purrr)
library(tidyr)
df %>%
# map each row to a defined function using pmap
# this function create a long table with 10 rows per ID, name, endValue
pmap(.f = function(...) {
x <- tibble(...)
y <- tibble(
ID = x$ID, name = x$name,
endValue = x$endValue,
LETTER = LETTERS[1:10],
value = c(rep("Y", x$endValue), rep("N", 10 - x$endValue)))
}) %>%
# combine all the df together
bind_rows() %>%
# then pivot_wider to get final result
pivot_wider(names_from = LETTER, values_from = value)
#> # A tibble: 3 x 13
#> ID name endValue A B C D E F G H I
#> <int> <chr> <dbl> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
#> 1 1 Bob 3 Y Y Y N N N N N N
#> 2 2 Jim 7 Y Y Y Y Y Y Y N N
#> 3 3 Fred 4 Y Y Y Y N N N N N
#> # … with 1 more variable: J <chr>
由 reprex package (v2.0.0) 于 2021 年 4 月 27 日创建