如何根据条件在R中上下移动整行?

问题描述 投票:3回答:2

假设我有一些看起来像这样的数据

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
r dataframe dplyr
2个回答
4
投票

这能满足你的需求吗?我使用了一个稍微编辑过的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)

0
投票

使用ifelsewhich可以实现另一种解决方案。我使用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))

Data

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)
© www.soinside.com 2019 - 2024. All rights reserved.