我有一个包含列的数据集" 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循环。
答案 0 :(得分:0)
我们可以将paste
和match
组合使用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
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),]