【问题标题】:Creating a function in R that transforms strings into integers, over the entire dataframe在 R 中创建一个函数,将字符串转换为整数,覆盖整个数据帧
【发布时间】:2019-04-04 15:46:20
【问题描述】:

我需要在 R 中创建一个函数,根据先前确定的“翻译代码”将数据帧的所有条目(字符串)转换为整数。

输入数据示例:

Question 1          Question 2    Question 3

Strongly Agree      Agree         Disagree

Strongly Disagree   Neutral       Don't Know

我将使用的数据集将包含 1000 多行和 50 列。每个答案都需要转换为整数值。翻译公式为:

非常不同意 = 1,不同意 = 2,中立 = 3,同意 = 4,非常同意 = 5,不知道 = 0。

所以这个样本数据的函数输出将是

Question 1  Question 2  Question 3

5           4           2

1           3           0

我的功能尝试:

transform <- function(x)

{
  for (i in x[i, ]

  {
  if (i == 'Discordo fortemente')  {i == 1}
  if (i == 'Discordo')  {i == 2}
  if (i == 'Não concordo nem discordo') {i == 3}
  if (i == 'Concordo')  {i == 4}
  if (i == 'Concordo fortemente')  {i == 5}
  if (i == 'Não sei dizer')  {i == 0}
  }

}

上面的语言是葡萄牙语。显然代码不起作用,我已经把头撞在墙上将近 2 个小时了。欢迎任何对我的问题的解决方案,尽管我的想法是构建一个适用于一列的函数,然后将它与 lapply 一起使用。

【问题讨论】:

    标签: r function loops


    【解决方案1】:

    我建议使用case_when 函数。例如

    library(dplyr)
    x %>& 
     mutate_all(~case_when(.x == 'Discordo fortemente' ~ 1,
                           .x == 'Discordo' ~ 2, 
                           .x == 'Não concordo nem discordo' ~ 3, 
                           .x == 'Concordo' ~ 4, 
                           .x == 'Concordo fortemente' ~ 5, 
                           .x == 'Não sei dizer' ~ 0))
    

    这里,x 是您的数据。此代码修改所有列。 如果您有其他不想转换的列,可以使用 mutate_at 代替 mutate_all 函数。

    如果你想让你的代码工作,你必须修改如下:

    transform <- function(x) {
    
      y <- seq_along(x)
    
      for (i in 1:length(x)) {
        if (x[i] == 'Discordo fortemente')  {y[i] = 1}
        if (x[i] == 'Discordo')  {y[i] = 2}
        if (x[i] == 'Não concordo nem discordo') {y[i] = 3}
        if (x[i] == 'Concordo')  {y[i] = 4}
        if (x[i] == 'Concordo fortemente')  {y[i] = 5}
        if (x[i] == 'Não sei dizer')  {y[i]= 0}
    }
    
      return(y)
    }
    
    transform(c("Discordo", 'Concordo fortemente', 'Não sei dizer'))
    [1] 2 5 0
    

    【讨论】:

    • 非常感谢。虽然我不得不说,随着您对我的代码的更正,我收到以下错误:Error in lapply(.x, .f, ...) : object 'i' not found
    • 感谢您的努力。我已经有了解决办法。尽管我必须通知您,您对我的代码的修复不起作用。我得到这个输出:[1] 5 5 5 5 5 5 4 4 9 10 5 12 4 2 15 4 17 4 1 2 21 5 5 4 25 2 1 1 29 5 31 5 4 2 1 5 5 38 2 1 5 4 43 2 1 2 4 5 49 5 4 [52] 52 2 5 55 4 2 1 2 60 4 5 63 5 4 66 1 2 69 4 5 72 There were 50 or more warnings (use warnings() to see the first 50)
    • 您可以在控制台中输入warnigs() 并发布输出。对我来说,代码有效。最后我举了一个小例子。如果您的问题得到解答,请考虑接受其中一个答案。
    • 1: In if (notas2[i] == "Discordo fortemente") { ... : the condition has length &gt; 1 and only the first element will be used 2: In if (notas2[i] == "Discordo") { ... : the condition has length &gt; 1 and only the first element will be used 3: In if (notas2[i] == "Não concordo nem discordo") { ... : 这持续了 50 条消息。
    • 上述函数仅在输入x是向量时有效,如果是data.frame则无效
    【解决方案2】:

    为什么不这样:

    library(dplyr)
    transform_fct <- function(var) {
      case_when(
        var == "Strongly disagree" ~  1,
        var == "Disagree" ~ 2,
        var == "Neutral" ~ 3,
        var == "Agree" ~ 4,
        var == "Strongly agree" ~ 5,
        var == "Don't know" ~ 0
      )
    }
    x <- x %>%
      mutate_all(transform_fct)
    

    【讨论】:

      【解决方案3】:
      for (i in colnames(x)) {
        x[,i] <- sapply(x[,i], function(j) switch(j,
                         "Discordo fortemente" = 1,
                         "Discordo" = 2,
                         "Não concordo nem discordo" = 3,
                         "Concordo" = 4,
                         "Concordo fortemente" = 5,
                         0))
      }
      

      如果您不想学习 dplyr,这种方法使用 base R,但总体上会变得笨拙。

      【讨论】:

        【解决方案4】:

        如果你有一致的情况,你可以这样做:

        mapping <- c(`Strongly disagree` = 1, Disagree = 2, Neutral = 3, Agree = 4,
          `Strongly agree` = 5, `Don't know` = 0.)
        
        df[] <- lapply(df, function(x) mapping[x])
        

        df[] <- mapping[unlist(df)]
        

        因为你没有,你可以做到:

        mapping <- setNames(mapping,toupper(names(mapping)))
        df[] <- lapply(df, function(x) mapping[toupper(x)])
        df
        #   Question.1 Question.2 Question.3
        # 1          5          4          2
        # 2          1          3          0
        

        df[] <- mapping[toupper(unlist(df))] # (same output)
        

        数据

        df <- read.table(header=TRUE,stringsAsFactors=FALSE,text="
        'Question 1'          'Question 2'    'Question 3'
        'Strongly Agree'      Agree         Disagree
        'Strongly Disagree'   Neutral       'Don\\'t Know'")
        

        【讨论】:

          猜你喜欢
          • 2020-05-21
          • 2021-01-01
          • 2021-01-22
          • 2011-05-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-10-06
          相关资源
          最近更新 更多