对于R中循环中的i
我一直在努力掌握一个基本的编程概念——对于R中循环中的i,r,R,我一直在努力掌握一个基本的编程概念——for循环。我通常处理体系结构数据,这样测量会重复使用唯一标识符的级别,如下所示: ID Measure 1 2 1 3 1 3 2 4 2 1 ... 通常,我需要创建一个新列来聚合ID中的数据,或者为ID的每个级别的每一行生成一个值。前者我使用base或dplyr中相当基本的函数,但对于后者,我希望养成为循环创建的习惯 因此,在本例中,我希望在假设的df中添加一列,这样新的列从每个ID的一列开始,并将1添加到后续的每一行,直到出现
for
循环。我通常处理体系结构数据,这样测量会重复使用唯一标识符的级别,如下所示:
ID Measure
1 2
1 3
1 3
2 4
2 1
...
通常,我需要创建一个新列来聚合ID
中的数据,或者为ID
的每个级别的每一行生成一个值。前者我使用base
或dplyr
中相当基本的函数,但对于后者,我希望养成为循环创建的习惯
因此,在本例中,我希望在假设的df
中添加一列,这样新的列从每个ID
的一列开始,并将1
添加到后续的每一行,直到出现新的ID
那么这个,
ID Measure NewVal
1 2 1
1 3 2
1 3 3
2 4 1
2 1 2
...
我很想学习计算方面的,但如果还有其他方法,我也很想听听。一种方法是使用splitstackshape
软件包。有一个函数名为getanID
。这是你的朋友。如果您的df被称为mydf
,您将执行以下操作。请注意,结果是data.table。如有必要,您希望将其转换为data.frame
library(splitstackshape)
getanID(mydf, "ID")
# ID Measure .id
#1: 1 2 1
#2: 1 3 2
#3: 1 3 3
#4: 2 4 1
#5: 2 1 2
数据
mydf <- structure(list(ID = c(1L, 1L, 1L, 2L, 2L), Measure = c(2L, 3L,
3L, 4L, 1L)), .Names = c("ID", "Measure"), class = "data.frame", row.names = c(NA,
-5L))
mydf我建议您不要为此使用for循环。这不是一个适合一个人的好地方。如果您愿意,您可以在plyr
(或dplyr
)中轻松完成此操作:
require(plyr)
x <- data.frame(cbind(rnorm(100), rnorm(100)))
x$ID <- sample(1:10, 100, replace=T)
new_col <- function(x) {
x <- x[order(x[,1]), ]
x$NewVal <- 1:nrow(x)
return(x)
}
x <- ddply(.data= x, .var= "ID", .fun= new_col)
require(plyr)
xseq_沿
给出一个从1开始的递增序列,其长度与其输入相同tapply
用于将功能应用于不同级别的输入。这里我们不关心提供了什么,因此您可以将ID
列应用于自身:
> d$NewVal <- unlist(tapply(d$ID, d$ID, FUN=seq_along))
> d
ID Measure NewVal
1 1 2 1
2 1 3 2
3 1 3 3
4 2 4 1
5 2 1 2
>d$NewVal d
ID度量NewVal
1 1 2 1
2 1 3 2
3 1 3 3
4 2 4 1
5 2 1 2
或者您可以使用ave
。优点是它将以与原始数据集中相同的顺序提供序列
,这在无序数据集中可能是有益的
transform(df, NewVal=ave(ID, ID, FUN=seq_along))
# ID Measure NewVal
#1 1 2 1
#2 1 3 2
#3 1 3 3
#4 2 4 1
#5 2 1 2
对于更一般的情况(如果ID
列为因子
)
或者如果订购了ID
列
df$NewVal <- sequence(tabulate(df$ID))
数据
df您还可以使用data.table
通过引用分配序列
做这种工作有很多选择。很高兴看到各种各样的选择。@jazzurro是的,但我喜欢你的方法。它很紧凑。
df$NewVal <- sequence(tabulate(df$ID))
library(dplyr)
df %>%
group_by(ID) %>%
mutate(NewVal=row_number())
df <- structure(list(ID = c(1L, 1L, 1L, 2L, 2L), Measure = c(2L, 3L,
3L, 4L, 1L)), .Names = c("ID", "Measure"), class = "data.frame",
row.names = c(NA, -5L))
# library(data.table)
setDT(mydf) ## convert to data table
mydf[,NewVal := seq(.N), by=ID] ## .N contains number of rows in each ID group
# ID Measure NewVal
# 1: 1 2 1
# 2: 1 3 2
# 3: 1 3 3
# 4: 2 4 1
# 5: 2 1 2
setDF(mydf) ## convert easily to data frame if you wish.