【问题标题】:Replace row values with multiple conditions in r用r中的多个条件替换行值
【发布时间】:2018-05-06 16:16:16
【问题描述】:

目前我正在做一个项目,但遇到了一个问题。我必须用不同列中的两个条件替换列的行值。假设:

x   y     m     n
1  200P  Jan  Perm
1  200T  Feb  Temp  
1  300P  Jan  Perm
2  200T  Feb  Temp      
2  300T  Feb  Temp
3  300P  Jan  Perm
3  400P  Jan  Perm

我想根据 x 和 y 更改第 n 列的值。

for each x
check the value of y and n, if the first value of y with T is 
Perm/Temp. Replace the rest of the values of unique x rows to that 
value.

我试过了,但是当我执行代码时,它会将所有 Temp 替换为 Perm 或 Perm 到 Temp。但我希望它只更改该唯一 x 的行的值。有人可以帮我解决这个问题。我希望我的输出是这样的:

x   y     m     n
1  200P  Jan  Temp
1  200T  Feb  Temp  
1  300P  Jan  Temp
2  200T  Feb  Temp      
2  300T  Feb  Temp
3  300P  Jan  Perm
3  400P  Jan  Perm

我正在尝试使用另一个具有不同条件的数据集进行练习。例如:

a   b    c       d
1   1   0.4    Minor
1   1   0.4    Minor
1   4   0.2    Minor
1   2   2.4    Major
2   4   0.2    Minor
3   1   0.4    Minor
3   4   0.2    Minor
3   4   4.2    Major

我正在尝试将 b 列中的 4 替换为 1,条件是如果它在 c 列中为 0.2。如果 4 和 0.4 在同一行,则将 4 替换为 1。

【问题讨论】:

  • 能否请您在问题文本中包含您想要的输出?解释有点模糊。

标签: r dataframe


【解决方案1】:

我相信以下代码可以满足您的需求。
它创建一个新列n2,其中n 的值对应于yT 的第一次出现。

fun <- function(DF){
    i <- grep("T", DF$y)[1]
    DF$n2 <- DF$n
    if(!is.na(i)) DF$n2[seq_len(nrow(DF))[-seq_len(i - 1)]] <- DF$n[i]
    DF$n2
}

res <- dat    # work with a copy
res$n2 <- unlist(lapply(split(dat[c(1:2, 4)], dat$x), FUN = fun))
res
#  x    y   m    n   n2
#1 1 200P Jan Perm Perm
#2 1 200T Feb Temp Temp
#3 1 300P Jan Perm Temp
#4 2 200T Feb Temp Temp
#5 2 300T Feb Temp Temp
#6 3 300P Jan Perm Perm
#7 3 400P Jan Perm Perm

如果您不想要那个新列,就这样做

res$n <- res$n2
res <- res[-ncol(res)]

编辑。

显然我的原始代码是正确的。以下是 OP 在最后一条评论中要求的内容。

fun2 <- function(DF){
    i <- grep("T", DF$y)[1]
    DF$n2 <- if(!is.na(i)) DF$n[i] else DF$n
    DF$n2
}

res2 <- dat    # work with a copy
res2$n2 <- unlist(lapply(split(dat[c(1:2, 4)], dat$x), FUN = fun))
res2
#  x    y   m    n   n2
#1 1 200P Jan Perm Temp
#2 1 200T Feb Temp Temp
#3 1 300P Jan Perm Temp
#4 2 200T Feb Temp Temp
#5 2 300T Feb Temp Temp
#6 3 300P Jan Perm Perm
#7 3 400P Jan Perm Perm

数据。

dat <- read.table(text = "
x   y     m     n
1  200P  Jan  Perm
1  200T  Feb  Temp  
1  300P  Jan  Perm
2  200T  Feb  Temp      
2  300T  Feb  Temp
3  300P  Jan  Perm
3  400P  Jan  Perm
", header = TRUE)

编辑 2.

有了问题编辑中的条件,使用逻辑索引就简单多了。
请注意,在您的编辑中,您首先说将列 b 的值从 4 更改为如果列 c0.2,然后您说如果列 c0.4 则更改它。下面的代码使用0.2

inx <- dat2$b == 4 & dat2$c == 0.2
dat2$b[inx] <- 1

数据 2。

dat2 <- read.table(text = "
a   b    c       d
1   1   0.4    Minor
1   1   0.4    Minor
1   4   0.2    Minor
1   2   2.4    Major
2   4   0.2    Minor
3   1   0.4    Minor
3   4   0.2    Minor
3   4   4.2    Major
", header = TRUE)

【讨论】:

  • 感谢您的帮助。我在我的数据集上尝试过它并没有改变值。是不是因为数据类型。我将 x 设为 num,其余设为 char。
  • @Rahul 我已将数据读取为 num,其他列读取为 factor。我也试过用stringsAsFactors = FALSE读取数据,结果是一样的,所以肯定有别的事情发生了。我的代码输出似乎是正确的。
  • 我发现了这个错误。您的解决方案不是我所期望的。具有 1 等的整个 x 组应替换为新值。我查看了我的数据集。一旦找到 T,它会替换之后的值,但它也应该替换以前的值。如果我的问题不清楚,我很抱歉。
  • @Rahul Done,看看是不是这个。
  • 您能否阅读添加的问题并帮助我理解您的代码。非常感谢您的帮助。
【解决方案2】:

我们也可以试试data.table

library(data.table)
i1 <- setDT(df1)[, {i1 <- grepl("T$", y)
            if(any(i1)) .I[which.max(i1):.N] } , x]$V1

或者

i1 <- setDT(df1)[, .I[cumsum(grepl("T$", y))!=0], x]$V1
df1[i1, n := first(n), x]
df1
#   x    y   m    n
#1: 1 200P Jan Perm
#2: 1 200T Feb Temp
#3: 1 300P Jan Temp
#4: 2 200T Feb Temp
#5: 2 300T Feb Temp
#6: 3 300P Jan Perm
#7: 3 400P Jan Perm

数据

df1 <- structure(list(x = c(1L, 1L, 1L, 2L, 2L, 3L, 3L), y = c("200P", 
"200T", "300P", "200T", "300T", "300P", "400P"), m = c("Jan", 
"Feb", "Jan", "Feb", "Feb", "Jan", "Jan"), n = c("Perm", "Temp", 
"Perm", "Temp", "Temp", "Perm", "Perm")), .Names = c("x", "y", 
"m", "n"), class = "data.frame", row.names = c(NA, -7L))

【讨论】:

    【解决方案3】:

    您可以使用dplyr::first 查找具有T 值的y1st 出现,然后将n 的所有值替换为找到的行中的值。

    library(dplyr)
    
    df %>% group_by(x) %>%
      mutate(n = ifelse(!is.na(first(grep("T$",y))), 
                                n[first(grep("T$",y))], n )) %>%
      as.data.frame()
    
    #   x    y   m    n
    # 1 1 200P Jan Temp
    # 2 1 200T Feb Temp
    # 3 1 300P Jan Temp
    # 4 2 200T Feb Temp
    # 5 2 300T Feb Temp
    # 6 3 300P Jan Perm
    # 7 3 400P Jan Perm
    

    数据:

    df <- read.table(text = 
    "x   y     m     n
    1  200P  Jan  Perm
    1  200T  Feb  Temp  
    1  300P  Jan  Perm
    2  200T  Feb  Temp      
    2  300T  Feb  Temp
    3  300P  Jan  Perm
    3  400P  Jan  Perm",
    header = TRUE, stringsAsFactors = FALSE)
    

    【讨论】:

      猜你喜欢
      • 2021-10-18
      • 2011-06-09
      • 1970-01-01
      • 2021-07-03
      • 1970-01-01
      • 1970-01-01
      • 2020-02-10
      • 2021-10-25
      • 2021-08-21
      相关资源
      最近更新 更多