R语言 一次从列表中添加1/0列

jvidinwx  于 2023-01-15  发布在  其他
关注(0)|答案(2)|浏览(168)

我有一个包含标识符和 Storm 类别的 Dataframe 。现在,类别在一列中,但我想为每个类别添加值为1或0的列。我不想将数据重新整形为宽的,因为在实际的数据集中有许多长格式变量需要保留。我目前使用的是一系列ifelse语句。但我觉得可能有更好的办法

library(dplyr)
library(tidyr)

df <- data.frame(
ID = c("A", "B", "C", "D", "A", "B", "C", "D", "A", "B", "C", "D"),
cat = c("TS", NA, NA, "TS", "1", "1", NA, NA, "2", NA, NA, NA)
)

df$cat_TS <- ifelse(df$cat == "TS", 1, 0) %>% replace_na(., 0)
df$cat_1 <- ifelse(df$cat == "1", 1, 0) %>% replace_na(., 0)
df$cat_2 <- ifelse(df$cat == "2", 1, 0) %>% replace_na(., 0)
db2dz4w8

db2dz4w81#

我们可以使用pivot_wider-创建一个序列列'rn',然后使用pivot_widervalues_fn重新整形为宽,lengthvalues_fill为0

library(dplyr)
library(tidyr)
library(stringr)
df %>% 
   mutate(rn = row_number(), cat1 = cat) %>% 
   pivot_wider(names_from = cat1, values_from = cat1, 
     values_fn = length, values_fill = 0, names_prefix = "cat_")%>%    
   select(-cat_NA, -rn)
  • 输出
# A tibble: 12 × 5
   ID    cat   cat_TS cat_1 cat_2
   <chr> <chr>  <int> <int> <int>
 1 A     TS         1     0     0
 2 B     <NA>       0     0     0
 3 C     <NA>       0     0     0
 4 D     TS         1     0     0
 5 A     1          0     1     0
 6 B     1          0     1     0
 7 C     <NA>       0     0     0
 8 D     <NA>       0     0     0
 9 A     2          0     0     1
10 B     <NA>       0     0     0
11 C     <NA>       0     0     0
12 D     <NA>       0     0     0

或使用fastDummies

library(fastDummies)
df %>% 
   dummy_cols("cat", remove_selected_columns = FALSE, ignore_na = TRUE) %>% 
   mutate(across(starts_with('cat_'), ~ replace_na(.x, 0)))
  • 输出
ID  cat cat_1 cat_2 cat_TS
1   A   TS     0     0      1
2   B <NA>     0     0      0
3   C <NA>     0     0      0
4   D   TS     0     0      1
5   A    1     1     0      0
6   B    1     1     0      0
7   C <NA>     0     0      0
8   D <NA>     0     0      0
9   A    2     0     1      0
10  B <NA>     0     0      0
11  C <NA>     0     0      0
12  D <NA>     0     0      0
jtw3ybtb

jtw3ybtb2#

基R的一个想法
首先,获取所有唯一的类别名称

cats <- unique(df$cat[!is.na(df$cat)])
cats
[1] "TS" "1"  "2"

然后在列cat中查找cats中每个条目的匹配项。另外,我将cat列保留在中以显示匹配正确。通过使用df$ID而不是df作为cbind中的第一个参数来删除它。

cbind(df, setNames(data.frame(sapply(seq_along(cats), function(x) 
  df$cat %in% cats[x]) * 1), cats))
   ID  cat TS 1 2
1   A   TS  1 0 0
2   B <NA>  0 0 0
3   C <NA>  0 0 0
4   D   TS  1 0 0
5   A    1  0 1 0
6   B    1  0 1 0
7   C <NA>  0 0 0
8   D <NA>  0 0 0
9   A    2  0 0 1
10  B <NA>  0 0 0
11  C <NA>  0 0 0
12  D <NA>  0 0 0

相关问题