【问题标题】:Add columns in a data frame whose column headers are unique values of another column在其列标题是另一列的唯一值的数据框中添加列
【发布时间】:2021-10-21 21:03:56
【问题描述】:

我不确定以前是否已经回答过此类特定类型的问题。我做了很多研究,但无法得到我想要的。我有一个包含许多列的数据集。其中两列是 Organic = c("Yes","Yes","No",...) 和 StoreBrand = c("No","Yes","No",...)。我想创建具有标题 Organic_Yes、Organic_No、StoreBrand_Yes 和 StoreBrand_No 的列,并用 0 和 1 填充它们。所以我的预期输出将是

Organic Organic_Yes Organic_No StoreBrand StoreBrand_Yes StoreBrand_No
Yes 1 0 No 0 1
Yes 1 0 Yes 1 0
No 0 1 No 0 1

.....等等。我想在 R 中执行此操作。感谢任何帮助

如果新的列标题不是通过蛮力创建的,那就太好了。我希望自动化创建这些列的过程。再次感谢!

【问题讨论】:

  • (1) 寻找带有model.matrix 之类的问题,因为这可能足以完成(大部分)此任务。 (2) 提供预期的输出是好的,请edit您的问题并添加您的起始数据(在这种情况下可以使用相同的格式)。
  • @r2evans 有没有 tidyverse 方法?
  • 可能,找到model.matrix 答案,您可能会找到建议 tidyverse 方法的同页答案。它们通常速度较慢和/或代码行数更多,但这是坚持使用 tidyverse 而不是 base-R 的代价。

标签: r dplyr


【解决方案1】:

这是另一种方法:使用 across 两次来操作 .names 参数(在此处学习:Using a function in .names argument of across function

library(dplyr)
library(stringr)
df %>% 
  mutate(across(everything(), ~ifelse(. == "Yes", 1, 0), .names ="{.col}_Yes"),
         across(contains("Yes"), ~ifelse(. == 1, 0, 1), .names = "{str_replace(.col,'_Yes', '_No')}"))

输出:

  Organic StoreBrand Organic_Yes StoreBrand_Yes Organic_No StoreBrand_No
1     Yes         No           1              0          0             1
2     Yes        Yes           1              1          0             0
3      No         No           0              0          1             1

【讨论】:

  • 这很有帮助!谢谢
【解决方案2】:

这是一个简单的 tidyverse 方法:

library(dplyr)

df %>% 
  mutate(Organic_Yes = as.numeric(Organic == "Yes"),
         Organic_No = 1 - Organic_Yes,
         Storebrand_Yes = as.numeric(StoreBrand == "Yes"),
         Storebrand_No = 1 - Storebrand_Yes) %>%
  select(Organic, Organic_Yes, Organic_No,
         StoreBrand, Storebrand_Yes, Storebrand_No)

#>   Organic Organic_Yes Organic_No StoreBrand Storebrand_Yes Storebrand_No
#> 1     Yes           1          0         No              0             1
#> 2     Yes           1          0        Yes              1             0
#> 3      No           0          1         No              0             1

或者更通用的 tidyverse 方法:

df %>% 
  mutate(across(everything(), 
                function(x) 1 * (x == "Yes"),
                .names = "{.col}_Yes")) %>%
  mutate(across(tidyselect::vars_select_helpers$where(is.character),
                function(x) 1 * (x == "No"),
                .names = "{.col}_No")) %>%
  select(order(names(.)))

#>   Organic Organic_No Organic_Yes StoreBrand StoreBrand_No StoreBrand_Yes
#> 1     Yes          0           1         No             1              0
#> 2     Yes          0           1        Yes             0              1
#> 3      No          1           0         No             1              0

reprex package (v2.0.0) 于 2021 年 10 月 21 日创建


数据

df <- data.frame(Organic    = c("Yes", "Yes", "No"),
                 StoreBrand = c("No", "Yes", "No"))

df
#>   Organic StoreBrand
#> 1     Yes         No
#> 2     Yes        Yes
#> 3      No         No

reprex package (v2.0.0) 于 2021 年 10 月 21 日创建

【讨论】:

  • 哇,暴力破解的方法 AllanCameron :-)
  • R 中的列标题可以自动化吗?所以像 paste("Organic","_", "Yes")?
  • @DebasmitaDas 是的,看看我的编辑
  • @r2evans 是的,有点懒惰。我添加了一种消除罪恶感的通用方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-25
  • 2022-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-25
相关资源
最近更新 更多