组内排序和w.r.t. R值

时间:2017-03-03 05:25:57

标签: r for-loop replace

我有一个包含列的数据集" Seq"和" N"具有不同的值(以下示例)。我想根据" N"插入一个ID号码。改变以及" Seq"的特定值。列即3(如果最后一行有3作为Seq,则将Serial更改为下一个数字)。我正在使用for循环。但由于数据集庞大,需要花费大量时间。还有其他办法。

数据集示例:

S    N    Seq 
1  BAC     1  
2  BAC     2  
3  BAC     3   
3  BAC     2   
4  ABC     1   
5  ABC     3      
6  ABC     3   
6  BGC     1   

我需要的例子:

S    N    Seq  Serial
1  BAC     1     1
2  BAC     2     1  #updated row
3  BAC     3     1
3  BAC     2     2
4  ABC     1     3
5  ABC     3     3   
6  ABC     3     4   #updated row(getting 3 only)
6  BGC     1     5

这是我正在使用的for循环:

for(i in 2:nrow(hjk1)){
  hjk1$Serial[1]=1 
  if(hjk1$N[i]!=hjk1$N[i-1])
    hjk1$Serial[i]<-hjk1$Serial[i-1]+1
  else
    if(hjk1$Seq[i-1]=3
    hjk1$Serial[i]<-hjk1$Serial[i-1]+1
  else
    hjk1$Serial[i]<-hjk1$Serial[i-1]
}

我需要替换这个for循环。

1 个答案:

答案 0 :(得分:0)

我们可以将pastematch组合使用na.locf

library(zoo)
v1 <- with(df1, paste(N, na.locf(replace(Seq, Seq==3, NA))))
df1$Serial <- match(v1, unique(v1))
df1$Serial
#[1] 1 1 2 3 3 4

或另一个选项是factor

df1$Serial <- as.integer(factor(v1, levels = unique(v1)))

或者我们可以使用tidyverse

library(tidyverse)
df1 %>%
   mutate(Seq1 = replace(Seq, Seq ==3, NA)) %>% 
   fill(Seq1) %>% 
   unite(N_Seq, N, Seq1, remove = FALSE) %>%
   mutate(Serial = match(N_Seq, unique(N_Seq))) %>% 
   select(-Seq1, -N_Seq)
#   S   N Seq Serial
# 1 1 BAC   1      1
# 2 2 BAC   3      1
# 3 3 BAC   2      2
# 4 4 ABC   1      3
# 5 5 ABC   3      3
# 6 6 BGC   1      4

更新

根据评论,我们可以做到

df1$Serial <- with(df1,  cumsum(c(FALSE, diff(Seq==3)< 0)|!duplicated(N)))
df1$Serial
#[1] 1 1 1 2 3 3 3 4

UPDATE2

df1$Serial <- with(df1, cumsum(!duplicated(cbind(c(0, cumsum(Seq[-length(Seq)]==3)), N))))
df1$Serial
#[1] 1 1 1 2 3 3 4 5

数据

df1 <- structure(list(S = 1:6, N = c("BAC", "BAC", "BAC", "ABC", "ABC", 
 "BGC"), Seq = c(1L, 3L, 2L, 1L, 3L, 1L)), .Names = c("S", "N", 
 "Seq"), class = "data.frame", row.names = c(NA, -6L))
###Update

df1<- rbind(df1,list(7,"BAC",2),list(8,"ABC",3)) 
df1<- df1[c(1,7,2,3,4,8,5,6),]