Reputation: 73
I have a data frame with columns "A", "B", and "Dict"
For example:
A B Dict
0 123 B
0 123 A
123 0 A
I want to move the value in "B" to "A" if "Dict" has A in the same row, but keep other rows the same if the "Dict" has correct matchings (the value should be in the column that "Dict" indicates, otherwise it will be 0):
A B Dict
0 123 B
123 0 A
123 0 A
Does anyone know how I should proceed?
Edit: There are negative values in the columns too. Sorry I should've clarified.
Upvotes: 3
Views: 1255
Reputation: 78927
Credits to Darren Tsai. Using his solution we could use A+B
instead of pmax
because of the 0:
With this dataframe:
df <- structure(list(A = c(0L, 0L, 123L), B = c(123L, 123L, 0L), Dict = c("B",
"A", "A")), class = "data.frame", row.names = c(NA, -3L))
library(dplyr)
df %>%
mutate(across(A:B, ~ ifelse(Dict == cur_column(), A+B, 0)))
I get this:
A B Dict
1 0 123 B
2 123 0 A
3 123 0 A
Upvotes: 2
Reputation: 35554
With dplyr
, you could use Dict == cur_column()
in across()
to determine where to swap A and B.
library(dplyr)
df %>%
mutate(across(A:B, ~ ifelse(Dict == cur_column(), pmax(A, B), pmin(A, B))))
A B Dict
1 0 123 B
2 123 0 A
3 123 0 A
Upvotes: 3
Reputation: 160437
Another base R:
ind <- dat$Dict != c("A","B")[max.col(dat[,c("A","B")])]
ind
# [1] FALSE TRUE FALSE
dat[ind,c("A","B")] <- dat[ind,c("B","A")]
dat
# A B Dict
# 1 0 123 B
# 2 123 0 A
# 3 123 0 A
Data
dat <- structure(list(A = c(0L, 123L, 123L), B = c(123L, 0L, 0L), Dict = c("B", "A", "A")), row.names = c(NA, -3L), class = "data.frame")
Upvotes: 3
Reputation: 1763
This might work :
df$A=ifelse(df$Dict=="A" & df$A==0,df$B,ifelse(df$Dict=="A",df$A,0))
df$B=ifelse(df$Dict=="B" & df$B==0,df$A,ifelse(df$Dict=="B",df$B,0))
df
A B Dict
1 0 123 B
2 123 0 A
3 123 0 A
Upvotes: 2