dplyr在循环内变异-问题

时间:2019-07-28 19:01:11

标签: r for-loop dplyr mutate

我正在使用tidyverse在R中执行数据分析和清理。 我有一个包含23列的数据框,其中包含值“ NO”,“ STEADY”,“ UP”和“ DOWN”。 我想将这23列中的所有值都更改为0(如果是'NO','STEADY',而将其更改为1)。

我所做的是,我使用名称键创建了一个列表,其中保存了所有列,然后使用for循环,ifelse语句和mutate。

请查看下面的代码

# 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))} 

它给我以下错误-

  

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

毕竟。我还尝试创建一个函数来获得所需的结果,但是那也不起作用:

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)}

我遇到了同样的错误:

  

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

请指导

3 个答案:

答案 0 :(得分:3)

使用mutate_at和case_when是一种更简单的方法。

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

mutate_at仅会使keys变量中指定的列发生突变。 case_when然后让您在某种条件下将一个值替换为另一个值。

答案 1 :(得分:3)

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

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

另一种方式,多亏Rui Barradas-

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

答案 2 :(得分:0)

这个通过forloop使用mutate的答案。

我没有您的数据,所以我尝试制作自己的数据,我使用tibble将密钥更改为enframe,然后将其散布到列中并将行号用作值对于每列,然后检查该值是否大于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) )
        }