Заменить значения строки несколькими условиями в r - PullRequest
0 голосов
/ 06 мая 2018

В настоящее время я работаю над проектом и застрял в одной проблеме. Я должен заменить значения строки столбца с двумя условиями в разных столбцах. Предположим:

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

Я хотел бы изменить значения столбца n на основе x и y.

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

Я пытаюсь заменить 4 на 1 в столбце b условием, что если это значение равно 0,2 в столбце c. Если 4 и 0.4 находятся в одном ряду, заменить 4 на 1.

Ответы [ 3 ]

0 голосов
/ 06 мая 2018

Мы также можем попробовать с 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))
0 голосов
/ 06 мая 2018

Вы можете использовать dplyr::first, чтобы найти 1st вхождение y со значением T, а затем заменить все значения 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)
0 голосов
/ 06 мая 2018

Я полагаю, что следующий код делает то, что вы хотите.
Создает новый столбец n2 со значениями n, соответствующими первому вхождению T в y.

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

РЕДАКТИРОВАТЬ.

Очевидно, мой исходный код был правильным.Ниже указано, что ОП запрашивает в последнем комментарии.

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 на, если столбец c равен 0.2, но затем вы говорите, чтобы изменить его, если столбец c равен 0.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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...