-1

I've seen the question How to use the which() function with a pipe %>% but it doesn't encapsulate the problem I am having. I would like to access the column names of a dataframe inside the which() function. For example, given the dataframe:

> df <- data.frame(ID=1:6, col1=c(0,1,2,0,5,0), col2=c("A1", "A2", "B1", "B2","C1", "A3"))
> df
  ID col1 col2
1  1    0   A1
2  2    1   A2
3  3    2   B1
4  4    0   B2
5  5    5   C1
6  6    0   A3

I can identify which rows in col1 have zero entries by doing:

row_zero <- which(df$col1 == 0 & grepl("A", df$col2, fixed=TRUE))
> row_zero
[1] 1 6

In order to avoid the repeated use of df$, I would like to apply a pipe. I tried the following (even using the tip from How to use the which() function with a pipe %>%), but it does not work:

> row_zero <- df %>% which(col1 == 0 & grepl("A", col2, fixed=TRUE))
Error in which(., col1 == 0 & grepl("A", col2, fixed = TRUE)) : 
  argument to 'which' is not logical
> row_zero <- df %>% { which(col1 == 0 & grepl("A", col2, fixed=TRUE)) }
Error: object 'col1' not found

Any suggestions on how to make the above work? Thank you.

3
  • 1
    Use reframe, e.g. df %>% reframe(which(col1 == 0 & grepl("A", col2, fixed=TRUE))) %>% unlist(use.names=F). For other data manipulation purposes mutate and summarize are common dplyr pipe verbs. Commented Jul 12 at 13:38
  • Based on your comment in the current answer, it seems that you may "need" more than just the indices of the columns. You say you want the column names, you get the column indices, and then ... what do you need with those? Neither of those is conducive to continuing data-manipulation in the same pipe. As Parfait suggested, I suggest you expand your question to identify what your next step (or 2-3) are, perhaps there is a more direct path to get there. BTW, your use of %>% suggests dplyr, please be specific if you are intending to use it or if you're trying to stay with base. Thanks! Commented Jul 12 at 17:17
  • For more detail on the dplyr-question ... this may be something for which where(.) or if_any(.) or similar can be used. Commented Jul 12 at 17:17

1 Answer 1

2

Rather than trying to make a pipe work, are you willing to use the with() function?

df <- data.frame(ID=1:6, col1=c(0,1,2,0,5,0), col2=c("A1", "A2", "B1", "B2","C1", "A3"))
with(df, which(col1 == 0 & grepl("A", col2, fixed=TRUE)))
#> [1] 1 6

And here is a solution with which() based on the answer linked by the OP. However, it doesn't avoid the use of $, just eliminates the need to type the data frame's name.

library(magrittr)
df <- data.frame(ID=1:6, col1=c(0,1,2,0,5,0), col2=c("A1", "A2", "B1", "B2","C1", "A3"))
df %>% {which(.$col1 == 0 & grepl("A", .$col2, fixed=TRUE))}  
#> [1] 1 6

<sup>Created on 2025-07-12 with [reprex v2.1.1](https://reprex.tidyverse.org)</sup>
Sign up to request clarification or add additional context in comments.

2 Comments

Hi. Thanks for that. If it's a one-off, I would use with() for sure! I would like to know if what I am trying to do is 'pipe-able' for more complex datasets where I would need to then perform further manipulations on the result.
You may need to expand your simple problem for the further manipulations on complex datasets. As run now, with() does not return a data frame and which() does not return a column. You may be asking an XY Problem. Give us the fuller problem to know why you need piping.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.