【问题标题】:dplyr mutate inside for loop - Issuedplyr 在 for 循环中发生变异 - 问题
【发布时间】:2019-12-06 05:13:46
【问题描述】:

我正在使用 tidyverse 在 R 中执行数据分析和清理。 我有一个包含 23 列的数据框,其中包含值“NO”、“STEADY”、“UP”和“down”。 如果是“NO”、“STEADY”,我想将这 23 列中的所有值更改为 0,在其他情况下更改为 1。

我所做的是,我按名称键创建了一个列表,其中我保留了所有列,之后我使用 for 循环、ifelse 语句和变异。

请看下面的代码

# Column names are kept in the list by name keys

keys = c('metformin', 'repaglinide', 'nateglinide', 'chlorpropamide', 'glimepiride', 
'glipizide', 'glyburide', 'pioglitazone', 'rosiglitazone', 'acarbose', 'miglitol', 
'insulin', 'glyburide-metformin', 'tolazamide', 'metformin-pioglitazone',
'metformin-rosiglitazone', 'glimepiride-pioglitazone', 'glipizide-metformin', 
'troglitazone', 'tolbutamide', 'acetohexamide')

之后,我使用以下代码来获得所需的结果:

for (col in keys){
  Dataset = Dataset %>%
    mutate(col = ifelse(col %in% c('No','Steady'),0,1)) }

我原以为它会做我需要的更改,但在此之后没有任何反应。 (没有错误消息,也没有想要的结果)

之后,我进一步研究并执行了以下代码

for (col in keys){
 print(col)}

它给了我列表中的元素,比如“二甲双胍”

所以,我想 - 可能这就是问题所在。因此,我使用下面的代码将键转换为符号:

keys_new = sym(keys)

之后我再次运行相同的代码:

for (col in keys_new){
   Dataset = Dataset %>%
     mutate(col = ifelse(col %in% c('No','Steady'),0,1))} 

它给了我以下错误-

匹配错误(x, table, nomatch = 0L): 'match' 需要向量参数

毕竟。我还尝试创建一个函数来获得所需的结果,但这也没有奏效:

change = function(name){
   Dataset = Dataset %>%
      mutate(name = ifelse(name %in% c('No','Steady'),0,1),
      name = as.factor(name))
      return(Dataset)}

for (col in keys){
   change(col)}

这没有执行任何操作。 (没有错误消息,也没有想要的结果)

当keys_new放在这段代码中时:

for (col in keys_new){
   change(col)}

我得到了同样的错误:

匹配错误(x, table, nomatch = 0L): 'match' 需要向量参数

请指导

【问题讨论】:

    标签: r for-loop dplyr


    【解决方案1】:

    这个答案使用 mutate through forloop

    我没有你的数据,所以我尝试制作自己的数据,我使用enframe 将键更改为tibble,然后将其分散到列中,并使用行号作为每列的值,然后检查该值是否大于10。

    要在 mutate 中使用列名,您必须在 mutate 函数中使用 !!:=

    df <- enframe(c('metformin', 'repaglinide', 'nateglinide', 'chlorpropamide', 'glimepiride', 
                     'glipizide', 'glyburide', 'pioglitazone', 'rosiglitazone', 'acarbose', 'miglitol', 
                     'insulin', 'glyburide-metformin', 'tolazamide', 'metformin-pioglitazone',
                     'metformin-rosiglitazone', 'glimepiride-pioglitazone', 'glipizide-metformin', 
                     'troglitazone', 'tolbutamide', 'acetohexamide')
    ) %>% spread(key = value,value = name)
    
    keys = c('metformin', 'repaglinide', 'nateglinide', 'chlorpropamide', 'glimepiride', 
             'glipizide', 'glyburide', 'pioglitazone', 'rosiglitazone', 'acarbose', 'miglitol', 
             'insulin', 'glyburide-metformin', 'tolazamide', 'metformin-pioglitazone',
             'metformin-rosiglitazone', 'glimepiride-pioglitazone', 'glipizide-metformin', 
             'troglitazone', 'tolbutamide', 'acetohexamide')
    
    
    for (col in keys){
            df = df %>%
                    mutate(!!as.character(col) := ifelse( df[col] > 10,0,100) )
            }
    

    【讨论】:

    • 非常感谢亲爱的........真的很丰富,正是我想要的
    • @AnkurKumarChhabra 请问你能把它作为答案吗?
    【解决方案2】:

    无需循环或跟踪列名。你可以使用mutate_all -

    Dataset %>% 
      mutate_all(~ifelse(. %in% c('No','Steady'), 0, 1))
    

    另一种方式,感谢 Rui Barradas -

    Dataset %>% 
      mutate_all(~as.integer(!. %in% c('No','Steady')))
    

    【讨论】:

    • 更简单:~as.integer(!. %in% c('No','Steady'))
    【解决方案3】:

    使用 mutate_at 和 case_when 有一个更简单的方法。

    Dataset %>% mutate_at(keys, ~case_when(. %in% c("NO", "STEADY") ~ 0, TRUE ~ 1))
    

    mutate_at 只会改变在 keys 变量中指定的列。 case_when 然后允许您通过某些条件将一个值替换为另一个值。

    【讨论】:

    • 更简单:~as.integer(!. %in% c("NO", "STEADY")).
    • 非常感谢。它对我有用。但是,如果您让我知道,我将非常感激,我可以从哪里详细研究 mutate_at 等这些函数
    • @AnkurKumarChhabra 大多数这些功能是 tidyverse 的一部分,它们链接到 their site 上的一些重要资源。 Rstudio 还为 tidyverse 维护了一个 cheat sheets 集合,非常方便。
    猜你喜欢
    • 1970-01-01
    • 2020-10-13
    • 2021-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-15
    • 2016-04-09
    • 1970-01-01
    相关资源
    最近更新 更多