r语言 - 循环遍历行并在满足条件时更改值



样本数据:

df <- data.frame(bucket = c("A", "B", "C", "D"),
apples = c("<4", "U", "22", "9"),
oranges = c("U", "<4", "15", "7"),
bananas = c("8", "6", "16", "<4"),
pears = c("U", "7", "<4", "10"))

我期望的输出:

bucket apples oranges bananas pears
1      A     <4       U       8     U
2      B      U      <4       6     7
3      C     22       U      16    <4
4      D      9       U      <4    10

这个想法是我试图替换最低的带字母"u"的数值在每个中。还请注意,我将"桶列"视为具有非唯一行。

然而,也有一些例外;

  1. 如果该行有多个"<4"实例,则不要更改该行中的任何内容。
  2. 如果该行已经有至少一个"U"实例,则不要更改该行中的任何内容。

我试过了:

for(i in 1:nrow(df)){

if(sum(df[i,] == "U") > 0 || sum(df[i,] == "<4") > 1){

next

} else {

df <- df %>%
rowwise() %>%
mutate(across(everything(),
~replace(.x, which.min(.x), "U")))
}
}

作为一个主要的tidyverse用户,我似乎无法理解如何正确使用rowwisemutateacross

一个整洁的宇宙解决方案是很棒的,但也很乐意采用其他解决方案。

一种方法是转换为长格式,再转换为宽格式,即

library(dplyr)
library(tidyr)
df %>% 
pivot_longer(-1) %>% 
group_by(bucket) %>% 
mutate(value1 = value, 
U_Exists = any(value == 'U'), 
value = as.numeric(value), 
value = replace(value, which.min(value), 'U'), 
value_final = ifelse(!U_Exists, value, value1), 
value_final = replace(value_final, is.na(value_final), value1[is.na(value_final)])) %>% 
select(-c(value, value1, U_Exists)) %>% 
pivot_wider(names_from = name, values_from = value_final)
# A tibble: 4 x 5
# Groups:   bucket [4]
bucket apples oranges bananas pears
<chr>  <chr>  <chr>   <chr>   <chr>
1 A      <4     U       8       U    
2 B      U      <4      6       7    
3 C      22     U       16      <4   
4 D      9      U       <4      10   

注意:(良性)警告是由于NAs转换为数值型。

相关内容

  • 没有找到相关文章