【问题标题】:Use only non-NA cells to replace cells in another column仅使用非 NA 单元格替换另一列中的单元格
【发布时间】:2020-01-15 11:52:27
【问题描述】:

长期听众,第一次来电,所以如果我在帖子或一般情况下遗漏了重要信息,我深表歉意。

简而言之,我有两列,其中一列填充了每个单元格(行为)。另一个(游戏)除了少数细胞外大多是NA,但每个细胞中的内容不一定相同。对于游戏中的每一个非NA,无论是什么内容,我都想用它来替换行为列中对应行的数据。

这是数据:

behavior<-c("run","jump","play","walk","jump","walk","run","play","jump","jump")
game<-c(NA,"tag",NA,NA,NA,"slide",NA,"tag",NA,"hopscotch")

    test<-data.frame(behavior,game)

behavior    game
1   run     NA
2   jump    tag
3   play    NA
4   walk    NA
5   jump    NA
6   walk    slide
7   run     NA
8   play    tag
9   jump    NA
10  jump    hopscotch

我希望它看起来像:

behavior    game
1   run     NA
2   tag     tag
3   play    NA
4   walk    NA
5   jump    NA
6   slide   slide
7   run     NA
8   tag     tag
9   jump    NA
10  hopscotch   hopscotch

我尝试使用 if/else 之类的 !(test$game==NA) 编写函数,但我认为我在这里缺少一些基本的东西。这看起来相当简单,但是在搜索了 stackoverflow 之后,我看到了大量关于如何替换 NA 的建议,但没有看到关于如何仅使用非 NA 来替换已经填充的单元格的建议。出于好奇,如果有办法交换单元格值,我也会感兴趣,所以第二行将是标签/跳转而不是标签/标签。很高兴提供任何额外的信息/澄清,任何建议都非常感谢。

【问题讨论】:

  • test$behavior[!is.na(test$game)] &lt;- test$game[!is.na(test$game)]
  • transform(test, behavior = ifelse(is.na(game), behavior, game))提供test&lt;-data.frame(behavior,game, stringsAsFactors = FALSE)
  • 如此快速和简单——非常感谢!!
  • 如果您想创建一个新列并保留原始数据,您可以这样做transform(test, behavior1 = ifelse(is.na(game), behavior, game))

标签: r replace rstudio swap


【解决方案1】:

将数据读取为字符串而不是因子

test<- data.frame(behavior,game, stringsAsFactors = FALSE)

我们可以将简单的ifelsetransform 一起使用,其中behavior 的值根据NAgame 列进行更改。

transform(test, behavior = ifelse(is.na(game), behavior, game))

#    behavior      game
#1        run      <NA>
#2        tag       tag
#3       play      <NA>
#4       walk      <NA>
#5       jump      <NA>
#6      slide     slide
#7        run      <NA>
#8        tag       tag
#9       jump      <NA>
#10 hopscotch hopscotch

factors 在内部存储为数字,如果您不将它们作为字符读取,则会产生相同的代码

test<- data.frame(behavior,game)
transform(test, behavior = ifelse(is.na(game), behavior, game))
#   behavior      game
#1         3      <NA>
#2         3       tag
#3         2      <NA>
#4         4      <NA>
#5         1      <NA>
#6         2     slide
#7         3      <NA>
#8         3       tag
#9         1      <NA>
#10        1 hopscotch

这将非常混乱且难以调试。或者,我们可以使用as.character 覆盖因子值,这将给出预期的输出。

transform(test, behavior = ifelse(is.na(game), as.character(behavior), 
                                               as.character(game)))

【讨论】:

  • 您能解释一下为什么将数据作为字符串而不是因子来读取很重要吗?
  • 当然,很好的答案!我只是认为说明为什么在这种情况下避免使用 stringsAsFactors 会很有用
【解决方案2】:

欢迎来到 SO。

感谢您提供一些示例数据,这真的很有帮助!

我会亲自使用dplyr 包和coalesce() 函数来解决这个问题(如果你熟悉SQL,你可能会认出这个函数,如果没有,别担心!)。

coalecse() 函数的作用是在两个或多个向量中获取第一个非 NA 值。您可以单独使用它,或者我更喜欢在 mutate() 函数(也来自 dplyr)中使用它,这对于在数据框中创建/修改列很有用:

library(dplyr)

behavior<-c("run","jump","play","walk","jump","walk","run","play","jump","jump")
game<-c(NA,"tag",NA,NA,NA,"slide",NA,"tag",NA,"hopscotch")

# Make the data frame, using stringsAsFactors = FALSE to make sure our data
# get treated as characters, not factors 
test <- data.frame(behavior = behavior, game = game, stringsAsFactors = FALSE)
dplyr::mutate(
     test,
     behavior = dplyr::coalesce(game, behavior)
)

    behavior      game
1        run      <NA>
2        tag       tag
3       play      <NA>
4       walk      <NA>
5       jump      <NA>
6      slide     slide
7        run      <NA>
8        tag       tag
9       jump      <NA>
10 hopscotch hopscotch

为了帮助可视化这一点,让我们创建一个新列(而不是覆盖behavior):

mutate(
     test,
     new = coalesce(game, behavior)
)

   behavior      game       new
1       run      <NA>       run
2      jump       tag       tag
3      play      <NA>      play
4      walk      <NA>      walk
5      jump      <NA>      jump
6      walk     slide     slide
7       run      <NA>       run
8      play       tag       tag
9      jump      <NA>      jump
10     jump hopscotch hopscotch

所以coalesce() 正在查看game,然后是behavior,如果game 中有值,则使用它,如果没有,则查看behavior 并使用该值(如果有两者都没有价值,它将使用NA)。

如果您喜欢这种方法,我建议您查看(优秀的)R for Data Science 书籍(在线免费:https://r4ds.had.co.nz/)和 tidyverse 软件包集合 (https://www.tidyverse.org/)。

【讨论】:

  • 最好创建一个新列并保留原始数据,谢谢!
猜你喜欢
  • 2019-05-16
  • 2022-01-22
  • 1970-01-01
  • 2015-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多