【问题标题】:Replace values in one column by taking values from another column通过从另一列中获取值来替换一列中的值
【发布时间】:2021-09-28 12:55:22
【问题描述】:

今天早上问了一个问题,现在我想问另一种替换方法,因为我正在等待我的老师确认物种名称。

我有一个这样的数据框(真正的df 是通过删除重复的行产生的)

df <- data.frame(name1 = c("a" , "b", "c", "a"),
                 name2 = c("x", NA, NA, NA),
                 name3 = c(NA, "b1", "c1", NA),
                 name4 = c("x", "b1", "c1", "a"))

  name1 name2 name3 name4
1     a     x  <NA>     x
2     b  <NA>    b1    b1
3     c  <NA>    c1    c1
4     a  <NA>  <NA>     a

如果name4 列中的值与name1 列匹配,我们可以通过调用将a 替换为x 吗?

我不想在这里直接使用和分配x,因为我的数据应该有很多这样的情况。请问有什么建议给我吗? (使用 base-R 对我来说也很好,因为我很想了解更多)

期望的输出

  name1 name2 name3 name4
1     a     x  <NA>     x
2     b  <NA>    b1    b1
3     c  <NA>    c1    c1
4     a  <NA>  <NA>     x

我对表格的解释和我的期望:

我有 3 列 name1、name2、name3(删除重复行后)。 Name4 列是最后一列,其中包含我想要的前 3 列的值。 name2 列中的值是我使用的第一优先级,然后是 name3 中的值。

在我的第四行中,由于 NA 值出现在 name2 列中,所以我从 name1 列中取了一个“a”。我在想是否可以在不分配 x 的情况下用 x 替换 a

【问题讨论】:

  • 您不想显式使用的“x”是否来自name1 有“a”的行中的name2 列?我不明白你想做什么
  • 对不起,我想我会混淆别人,我会关闭并问另一个更清楚。
  • 您不应该删除许多用户已经花时间给您答案的问题。相反,您应该通过编辑来改进您的问题。
  • 您仍然没有回答 cmets 中的问题。 x 值来自哪里(如果它不应该被硬编码)?替换值应该遵循什么逻辑?
  • 所以让我们从一开始就说,我有 3 列 name1、name2、name3(在删除重复的行之后)。 Name4 列是最后一列,其中包含我想要的前 3 列的值。 name2 列中的值是我使用的第一优先级,然后是 name3 中的值

标签: r tidyverse


【解决方案1】:

据我了解,您定义 name4 的标准是:

  1. 如果可用,请使用同一行中的name2
  2. 如果可用,请使用同一行中的 name3
  3. 别管它(暂时)
  4. 使用共享相同name1 值的先前行中的name4 值填充缺失的name4 值。

如果您想要基于 tidyverse 的解决方案:

library(dplyr)
library(tidyr)

df <- data.frame(name1 = c("a" , "b", "c", "a"),
                 name2 = c("x", NA, NA, NA),
                 name3 = c(NA, "b1", "c1", NA))

result <- df %>% 
  mutate(name4 = case_when(
    #!is.na(name4) ~ name4, # when name4 is not missing, use it? If you like...
    !is.na(name2) ~ name2, # when name2 is not missing, use it
    !is.na(name3) ~ name3, # when name3 is not missing, use it
    TRUE ~ NA_character_   # leave a NA for now otherwise
  )) %>%
  group_by(name1) %>%
  fill(name4, .direction = c("down")) %>% # Fill each group looking at the previous non-missing row.
  ungroup()

返回:

# A tibble: 4 × 4
  name1 name2 name3 name4
  <chr> <chr> <chr> <chr>
1 a     x     NA    x    
2 b     NA    b1    b1   
3 c     NA    c1    c1   
4 a     NA    NA    x   

注意fill可以填充多个方向,如果要先从上到下再从下到上填充,可以使用“downup”。

【讨论】:

  • 非常感谢,可以理解。但是,我意识到既然 name4 列已经存在,那么即使是我想保留在 name4 列中的名称也会给出 NA 值。
  • 我们所有人遇到的主要问题是了解您的要求、标准以及您想要做什么。您能做的最好的事情就是改进您的问题并阐明您需要做什么。我试图在回答中解释我从您的问题中理解的要求,但它们不正确。您能否复制我关于标准的初始段落/列表并对其进行更改,使其符合您的预期(如何处理现有的 name4 列)?那么我们应该更容易帮助您找到您想要的解决方案。
【解决方案2】:

您可以按name1 分组,如果name1name4 相等,则将name4 值替换为第一个可用的非NA 值。

library(dplyr)

df %>%
  group_by(name1) %>%
  mutate(name4 = ifelse(name1 == name4, na.omit(unlist(cur_data()))[1], name4)) %>%
  ungroup

# name1 name2 name3 name4
#  <chr> <chr> <chr> <chr>
#1 a     x     NA    x    
#2 b     NA    b1    b1   
#3 c     NA    c1    c1   
#4 a     NA    NA    x    

【讨论】:

  • 该代码适用于我的可重现数据,但它不适用于我的数据:(。运行代码后该值保持不变
  • 您是否将输出分配回数据帧? df &lt;- df %&gt;% group_by(name1) ... ?
  • 它运作良好,伙计。但是,如果我在 name1 和 name2 列之间还有一列怎么办。因为如果我有那一列,代码将无法正常工作。
  • 如果您只想从特定列中选择值,您可以将na.omit(unlist(cur_data()))[1] 更改为na.omit(unlist(select(cur_data(), name1, name2)))[1]
  • 我刚刚意识到我还需要将 name3 列作为 name2 列。如果 name1 == name 4,则取 name3 中的值替换 name4 中的值(同上)。但现在 name1 将包含一些 NA 值。我再次尝试了上面的代码,但现在看起来很奇怪。你能看一下吗
【解决方案3】:

你可以这样做:

df[which(df$name1==df$name4), "name4"] <- "x"

基本上,这意味着子集您的数据框选择行,其中name1 == name4name4 列,然后将这些值更改为“x”

【讨论】:

  • 或类似:df$name4[df$name1 == df$name4] &lt;- "x"(只是口味问题)
  • 是的,但我们在这里准确地调用 x。我不想在这里使用它。因为如果我有很多案例怎么办。
  • 请澄清您的意思。建议的解决方案导致您提到的结果
  • 我上面的评论已经更新了,请看一下。
【解决方案4】:

基Rifelse解决方案:

df$name4 <- ifelse(df$name1 == df$name4, "x", df$name4)

根据您的更新,使用dplyrfirst

library(dplyr)

df$name4 <- ifelse(df$name1 == df$name4, first(df$name4), df$name4)

执行以下操作:

  • 检查 name1 是否等于 name 4
  • 如果 name1 等于 name4,它会将 name4 的值替换为 name4 出现的第一个值。

结果:

  name1 name2 name3 name4
1     a     x  <NA>     x
2     b  <NA>    b1    b1
3     c  <NA>    c1    c1
4     a  <NA>  <NA>     x

【讨论】:

  • 我试过了,但它不起作用,因为它自动在 name4 列中为我的基于 name1 的值(即 a)的真实数据提出了许多重复的行
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-22
  • 2019-03-28
  • 1970-01-01
  • 1970-01-01
  • 2021-11-09
  • 1970-01-01
相关资源
最近更新 更多