Я хотел бы пометить строки на основе условия в других строках.
в основном, я ищу, если строка NA, тогда ищите строку с не-NA и используйте ее столбец sd_value, чтобы решить, пометить ли строку NA ее меткой, иначе пометить ее NA. Надеюсь, это объяснение понятно.
Итак, скажем, у нас есть
df <- data.frame(value = c(0.5,1,0.6,1.2), sd_value=c(0.1,0.5,0.2,0.8),
label = c("good", "bad",NA,NA))
> df
value sd_value label
1 0.5 0.1 good
2 1.0 0.1 bad
3 0.6 0.5 NA
4 1.2 0.8 NA
чтобы пометить, например, строку 3, мне нужно проверить значение этой строки, а затем проверить, лежат ли они между 'good' или 'bad' value±2*sd_value. Если да, обозначьте их good или bad.
ожидаемый результат
> df
value sd_value label
1 0.5 0.1 good
2 1.0 0.1 bad
3 0.6 0.5 good #because 0.6 is ±2*sd_value of 1st row value
4 1.2 0.8 bad #because 1.2 is ±2*sd_value of 2nd row value
чтобы обобщить вопрос, скажем, у нас есть такие данные
df <- data.frame(value = c(0.5, 1,8, 1.2, 2.4,0.4,6,2,5.7, 9),
sd_value=c(0.1, 0.1,1, 0.2,0.2,0.1,0.4,0.2,0.1,0.1),
label = c("good",NA,"beautiful","bad", NA,NA,"ugly","dirty",NA,NA))
> df
value sd_value label
1 0.5 0.1 good
2 1.0 0.1 <NA>
3 8.0 1.0 beautiful
4 1.2 0.2 bad
5 2.4 0.2 <NA>
6 0.4 0.1 <NA>
7 6.0 0.4 ugly
8 2.0 0.2 dirty
9 5.7 0.1 <NA>
10 9.0 0.1 <NA>
В зависимости от условий ожидаемый результат должен выглядеть так
> df
value sd_value label
1 0.5 0.1 good #original label
2 1.0 0.1 bad
3 8.0 1.0 beautiful #original label
4 1.2 0.2 bad
5 2.4 0.2 dirty
6 0.4 0.1 good
7 6.0 0.4 ugly #original label
8 2.0 0.2 dirty #original label
9 5.7 0.1 ugly
10 9.0 0.1 beautiful
эти измененные строки NA основаны на значении ±2*sd_value строк, не относящихся к NA.
И первое, и второе NA лежат между 2 sd от первого (хорошего) и второго значения (плохого). Как вы определяете хорошее или плохое? Ближайший?
@akrun yes.3-е значение (0,6) <= 0,7. Поэтому он должен быть помечен как good. перед ожидаемым результатом я попытался подчеркнуть это.
@ c1au61o_HH да, самый близкий. Таким образом я определил некоторые sd_value для принятия решения.
@akrun извини. исправил эту проблему NA.
Кроме того, еще одно сомнение, если у вас есть несколько good/bad, как в исходных данных, по каким критериям проверять NA
@akrun ау! Я обнаружил проблему, связанную с c1au61o_HH. Таким образом, sd_values обновляется в исходных данных!. Извините еще раз! мой плохой!
@akrun Критерий - просто строка NA или нет. У меня хорошо определены реальные данные хорошие/плохие sd_values.
Разве это не i1 <- df[-(1:2), ]$value < df$value[1] + 2 * df$sd_value[1]; df$label[3:4] <- c("bad", "good")[(i1+1)]
@akrun да. но предпочитаете иметь решение в dplyr и, возможно, написать небольшую функцию? Я не мог понять как :(
Чем именно это отличается от вопроса, который вы уже разместили сегодня?
@camille Я немного расширил OP, чтобы обобщить способ решения.
@Alexander Александр При применении кодов к последнему набору данных он соответствует другой метке. Это ожидаемый результат?
да. Я расширил исходный набор данных и немного смешал строки.
@akrun блестящее решение с cut. Акрун, спасибо!





Мы можем подмножить значения строки NA и проверить, что с помощью «значения», «sd», соответствующего метке «хорошо», изменить логический вектор («i2») на «хороший/плохой» либо с числовой индексацией, либо с использованием ifelse и назначьте вывод обратно столбцу на основе индекса ('i1')
i1 <- is.na(df$label)
i2 <- df$value[i1] < abs(df$value[1] + 2 * df$sd_value[1])
df$label[i1] <- c("bad", "good")[(i2 + 1)]
Его можно обернуть в функцию
f1 <- function(data, lblCol, valCol, sdCol){
i1 <- is.na(df[[lblCol]])
gd <- which(df[[lblCol]] == "good")
i2 <- df[[valCol]][i1] < abs(df[[valCol]][gd] + 2 * df[[sdCol]][gd])
df[[lblCol]][i1] <- c("bad", "good")[(i2 + 1)]
df
}
f1(df, "label", "value", "sd_value")
# value sd_value label
#1 0.5 0.1 good
#2 1.0 0.5 bad
#3 0.6 0.2 good
#4 1.2 0.8 bad
С обновленным набором данных мы извлекаем строки, в которых «метка» не является NA, arrange в порядке возрастания и используем это в cut, чтобы вырезать «значение», чтобы получить правильную «метку».
library(dplyr)
df1 <- df %>%
filter(!is.na(label)) %>%
transmute(label, v1 = value + 2 * sd_value) %>%
arrange(v1)
df %>%
mutate(label = cut(value, breaks = c(-Inf, df1$v1), labels = df1$label))
# value sd_value label
#1 0.5 0.1 good
#2 1.0 0.1 bad
#3 8.0 1.0 beautiful
#4 1.2 0.2 bad
#5 2.4 0.2 dirty
#6 0.4 0.1 good
#7 6.0 0.4 ugly
#8 2.0 0.2 dirty
#9 5.7 0.1 ugly
#10 9.0 0.1 beautiful
Или та же логика в base R
df1 <- transform(na.omit(df), v1 = value + 2 * sd_value)[3:4]
df$label <- cut(df$value, breaks = c(-Inf, df1$v1), labels = df1$label)
Я знал, что это сложная проблема. Как вы думаете, Akrun может быть универсальным способом сделать это? Например, найдите строку NA и найдите строки, не относящиеся к NA, и их sd_values, чем если бы это значение строки NA было ближе к метке значения, отличной от NA, такой же, как они. Было бы здорово, если бы он у нас был. Недурно!
@Alexander В функции более широко используется поиск «хорошей» строки, извлечение значения и затем сравнение. Конечно, предполагается, что есть только одна хорошая/плохая строка (по этой причине я прокомментировал этот случай ранее).
@Alexander Кроме того, здесь мы не проверяем «плохую» строку, поскольку противоположность «хорошей» считается «плохой».
@Ну у меня хорошие baduglydirty и beautiful тоже :) В таком случае эта функция меня немного сдерживает, верно?
@Александр Хм. В таком случае придется внести небольшие коррективы в функцию, добавив bd <- which(df[[lblCol]] == "bad") Допустим, если "хорошее" условие ложно, то куда оно естественным образом попадает?
их расположение на самом деле случайно в реальных данных. Ok. Я обновлю ОП. Следите за обновлениями.
Я обновил ОП. Пожалуйста, смотрите конец вопроса. Ваше здоровье!
Разве 3-е значение не проверяется на основе
0.5 + 0.1 * 2=0.7