假设我有一些看起来像这样的数据
Name Type Rating
Dave Good 3.0
Steve Bad 0.0
Steve Good 2.0
Dave Bad 1.0
Tom Bad 2.0
Marianne Good 0.0
Tom Bad 1.0
Steve Bad 5.5
Marianne Bad 3.0
我想采取满足条件'type =='good''和'Rating == 2.0'的任何行,并将整行向上或向下移动1行。我将如何在R中这样做呢?
所以它看起来像这样。
Name Type Rating
Dave Good 3.0
Steve Good 2.0
Steve Bad 0.0
Dave Bad 1.0
Tom Bad 2.0
Marianne Good 0.0
Tom Bad 1.0
Steve Bad 5.5
Marianne Bad 3.0
这能满足你的需求吗?我使用了一个稍微编辑过的data.frame
来展示它如何处理边缘情况(即你想向下移动,但你已经在最后一行)。
rows <- rep(which(df$Type == "Good" & df$Rating == 2.0), each = 2)
all_rows <- 1:nrow(df)
#For moving DOWN change "-" to "+"
all_rows[replace(rows - c(1,0), rows - c(1,0) > nrow(df) | rows - c(1,0) < 1, NA) %>% na.omit] <- replace(rows - c(0,1), rows - c(0,1) > nrow(df) | rows - c(0,1) < 1, NA) %>% na.omit
df[all_rows,]
# Name Type Rating
#1 Mike Good 2.0
#2 Dave Good 3.0
#4 Steve Good 2.0
#3 Steve Bad 0.0
#5 Dave Bad 1.0
#6 Tom Bad 2.0
#7 Marianne Good 0.0
#8 Tom Bad 1.0
#9 Steve Bad 5.5
#11 Steve Good 2.0
#10 Marianne Bad 3.0
数据:
df <- read.table(text="Name Type Rating
Mike Good 2.0
Dave Good 3.0
Steve Bad 0.0
Steve Good 2.0
Dave Bad 1.0
Tom Bad 2.0
Marianne Good 0.0
Tom Bad 1.0
Steve Bad 5.5
Marianne Bad 3.0
Steve Good 2.0", header = T)
使用ifelse
和which
可以实现另一种解决方案。我使用data.frame
回答的@MikeH
来包括最终条件。
matched <- which(df$Type == "Good" & df$Rating == 2.0 )
all <- 1:nrow(df)
#move up by 1
swapped_row <- ifelse(all %in% (matched-1), all+1,
ifelse(all %in% matched & all != 1, all-1, all))
df[swapped_row,]
# Name Type Rating
#1 Mike Good 2.0
#2 Dave Good 3.0
#4 Steve Good 2.0
#3 Steve Bad 0.0
#5 Dave Bad 1.0
#6 Tom Bad 2.0
#7 Marianne Good 0.0
#8 Tom Bad 1.0
#9 Steve Bad 5.5
#11 Steve Good 2.0
#10 Marianne Bad 3.0
# A bit generic way to cover 1+ row shift up
n = 1 # 1 to move up by 1
swapped_row <- ifelse(all %in% (matched-n), all+n,
ifelse(all %in% matched & all>n , all-n, all))
# A bit generic way to cover 1+ row shiftdown
n = -1 # -1 to move down by 1
swapped_row <- ifelse(all %in% (matched-n), all+n,
ifelse(all %in% matched & all<(n+length(all)) , all-n, all))
df <- read.table(text="Name Type Rating
Mike Good 2.0
Dave Good 3.0
Steve Bad 0.0
Steve Good 2.0
Dave Bad 1.0
Tom Bad 2.0
Marianne Good 0.0
Tom Bad 1.0
Steve Bad 5.5
Marianne Bad 3.0
Steve Good 2.0", header = T)