简体   繁体   中英

Speading manipulation on data.frame with dplyr in R

I have a large data.frame structured like the following example df

df <- data.frame(id = c(rep("A",3), rep("B", 2), rep("C", 4)), 
                 x = c(paste0(letters[1:3],1) , paste0(letters[1:2],3), 
                       paste0(letters[1:4], 1)) , 
                 y = 1:9, z = 2:10 )
#   id  x y  z
# 1  A a1 1  2
# 2  A b1 2  3
# 3  A c1 3  4
# 4  B a3 4  5
# 5  B b3 5  6
# 6  C a1 6  7
# 7  C b1 7  8
# 8  C c1 8  9
# 9  C d1 9 10

In the real dataset there is an additional dimension (time) and there are many more numerical columns. I would like to manipulate df using the dplyr package (because it seems fast at these kind of operations) in the following way.

  1. I need to subtract the y and z values for x equal to b1 for id == A ( row = 2 ), to a3 for id == B ( row = 4 ) and to a1 for id == C ( row = 6 ) from the remaining y and z values of A , B and C respectively.

  2. delete the rows that have been subtracted.

The resulting data.frame would be

#   id  x y  z
# 1  A a1 -1 -1
# 2  A c1 1  1
# 3  B b3 1  1
# 4  C b1 1  1
# 5  C c1 2  2
# 6  C d1 3  3

In the real data.frame I have multiple numeric columns (which I didn't show for simplicity) so that these operations should be applied to all columns. Notice that the codes in x must refer to the id because different id can have the same x codes (for example A and C ).

I found this possible solution:

df %>%
  mutate(cond = ifelse( (id == "A" & x == "b1") | ( id == "B" & x == "a3" ) | ( id == "C" & x == "a1" ) , 1, 0 ) ) %>%
  group_by(id) %>%
  mutate_at(vars("y", "z"),funs(.-.[cond==1])) %>%
  filter(cond == 0)

it seems to work. Better/faster ideas?

If you're open to a data.table solution, this should be fast:

library(data.table)
setDT(df)
keys <- data.table(id=c("A","B","C"), x=c("b1","a3","a1"))
onv <- c("id","x")
vars <- c("y","z")
df[df[keys, on=onv], on=onv[1], (vars) := .SD[,..vars] - mget(paste0("i.", vars))][!keys, on=onv]

#   id  x  y  z
#1:  A a1 -1 -1
#2:  A c1  1  1
#3:  B b3  1  1
#4:  C b1  1  1
#5:  C c1  2  2
#6:  C d1  3  3

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM