使用dplyr在 Dataframe 上对列变量进行条件性逐行筛选

pxiryf3j  于 2023-06-27  发布在  其他
关注(0)|答案(2)|浏览(72)

这是我的虚拟数据:

dummy_data <- data.frame (name  = c("apple", "apple", "orange", "orange", "orange", "kiwi", "kiwi", "kiwi"),
                values = c("value_1", "value_2", NA,"value_2","value_3","value_3", NA, "value_3"),
                data = c("1234","2345","3456","4567","5678","6789","7890","1245"))

    name  values data
1  apple value_1 1234
2  apple value_2 2345
3 orange    <NA> 3456
4 orange value_2 4567
5 orange value_3 5678
6   kiwi value_3 6789
7   kiwi    <NA> 7890
8   kiwi value_3 1245

好了,我想过滤name = 'kiwi',values = 'value_3'和number = 6789的行。我希望这是有条件的,因为它进入了一个大数据集的循环。一些值为NA。
所以期望的结果是行#6:

name  values data
6 kiwi value_3 6789

fruit_name是我的动态赋值变量,在其中一个循环中它将是'kiwi',value是我的动态赋值变量,在那个循环中它将是'value_3',number对于6789是相同的。
我现在拥有的:

fruit_name <- 'kiwi'
value <- 'value_3'
number <- "6789"

期望行为:filter for fruit_name(name col)and number(data col),如果该ROW的values列不是NA,则filter value = value_3(对于这个循环,我没有展示循环结构)。如果它是NA,那么就保持值为NA,不要过滤它。

df <- df %>% filter(name == fruit_name & data == number) %>%
           mutate( value = ifelse(!is.na(value), number, TRUE))

然而,这实际上不是过滤,它只是返回变量编号。我想过滤一下。我也试着为第二行做一些类似的事情:

filter(number %in% values)

filter(if (!is.na(value)) values == number else TRUE)

这会产生一个错误:

  • 条件的长度> 1,并且只使用第一个元素 *

来源
但都不管用我被困在这里了,希望你能给点建议。谢谢你

第二个问题的附加数据(与原始问题无关):

环结构:
这是我希望在我的数据框中查找与虚拟数据匹配的数据的列表/键:

list <- (fruit = c("apple", "orange", "kiwi", "kiwi"), 
vals1 = ("value_2", "value_1", "value_3", "value_3"), 
vals2 = c("4567", "5678", "6789", "4567") )

for (i in seq_len(nrow(list))) {

f_name  <- list$fruit[i]
val1  <- list$vals1[i]
val2   <- list$vals2[i]

assign(paste("df_", i, sep=""), dummy_data %>%  filter(name == f_name & data == val2, if(is.na(values)) is.na(values) else values == val1) )

}

所需输出:df_1、df_2等,以用于稍后的不同处理。

q8l4jmvw

q8l4jmvw1#

可以使用if条件:
假设你的df如下:

df <- df %>%add_row(name='kiwi', data='6789')

然后为:

fruit_name <- 'kiwi'
value <- 'value_3'
number <- 6789

df %>%
  filter(name == fruit_name, data == number, 
         if(is.na(value))is.na(values) else values == value)

  name  values data
1 kiwi value_3 6789
fruit_name <- 'kiwi'
value <- NA
number <- 6789

df %>%
   filter(name == fruit_name, data == number, 
          if(is.na(value))is.na(values) else values == value)
  name values data
1 kiwi   <NA> 6789

注意我维护了相同的代码

编辑

您也可以简单地执行以下操作:

subset(df, do.call(paste, df) == paste(fruit_name, value, number))

编辑二:

给定列表格式的数据,您可以用途:

merge(dummy_data, list, by.x = names(dummy_data), by.y = names(list))
  name  values data
1 kiwi value_3 6789
u3r8eeie

u3r8eeie2#

这台计算机没有安装R,所以我的测试能力有限,但您可以尝试

df <- df %>%
 filter( 
    name == fruit_name,  # comma works like an &
    data == number,
    is.na(values) | values == value
  )

以下是评论意见:

df |>
  add_row(name = 'kiwi', data = '6789') |>
  dplyr::filter( 
    name == fruit_name,  # comma works like an &
    data == number,
    is.na(values) | values == value
  )

保留NA行和值行。
这里有一个解决方案,只保留没有NA的一个:

df |>
  add_row(name = 'kiwi', data = '6789') |>
  dplyr::filter( 
    name == fruit_name,  # comma works like an &
    data == number,
    {if(all(is.na(values))) TRUE else values == value}
  )

相关问题