我对R和编程很新。我刚刚开始学习如何使用for循环,但我无法弄清楚如何获取我想要打印的变量作为我的数据帧的一部分。
我的数据看起来像这样:
Place Sex Length
A M 32
A M 33
A F 35
A F 35
A F 35
A F 39
B M 30
B F 25
B F 28
B F 28
我想在我的数据框中创建第四个变量,它为每行数据提供一个特定于其Place/Sex/Length
组合的唯一标识符,以便我的数据看起来像这样,因此每个人都有一个唯一的{{ 1}}仅适用于该行数据的组合:
Place/Sex/Length/ID
提前感谢您的任何建议。我一直在寻找一些帮助,如何做到这一点,没有运气。
答案 0 :(得分:4)
一种(多种)方法是在基础R中使用ave
,如下所示(假设data.frame
名为“temp”)
within(temp, {
ID <- ave(as.character(interaction(temp)),
interaction(temp), FUN = seq_along)
})
# Place Sex Length ID
# 1 A M 32 1
# 2 A M 33 1
# 3 A F 35 1
# 4 A F 35 2
# 5 A F 35 3
# 6 A F 39 1
# 7 B M 30 1
# 8 B F 25 1
# 9 B F 28 1
# 10 B F 28 2
尝试运行interaction(temp)
以了解它正在做什么。
答案 1 :(得分:3)
另一种方式:
# assuming the data.frame is already sorted by
# all three columns (unfortunately, this is a requirement)
> sequence(rle(do.call(paste, df))$lengths)
# [1] 1 1 1 2 3 1 1 1 1 2
分解:
do.call(paste, df) # pastes each row of df together with default separator "space"
# [1] "A M 32" "A M 33" "A F 35" "A F 35" "A F 35" "A F 39" "B M 30" "B F 25" "B F 28"
# [10] "B F 28"
rle(.) # gets the run length vector
# Run Length Encoding
# lengths: int [1:7] 1 1 3 1 1 1 2
# values : chr [1:7] "A M 32" "A M 33" "A F 35" "A F 39" "B M 30" "B F 25" "B F 28"
$lengths # get the run-lengths (as opposed to values)
# [1] 1 1 3 1 1 1 2
sequence(.) # get 1:n for each n
# [1] 1 1 1 2 3 1 1 1 1 2
由于有很多解决方案,我认为我会在相对较大的data.frame
上对此进行基准测试。所以,结果如下(我还添加了一个解决方案data.table
)。
以下是数据:
require(data.table)
require(plyr)
set.seed(45)
length <- 1e3 # number of rows in `df`
df <- data.frame(Place = sample(letters[1:20], length, replace=T),
Sex = sample(c("M", "F"), length, replace=T),
Length = sample(1:75, length, replace=T))
df <- df[with(df, order(Place, Sex, Length)), ]
Ananda的ave
解决方案:
AVE_FUN <- function(x) {
i <- interaction(x)
within(x, {
ID <- ave(as.character(i), i, FUN = seq_along)
})
}
Arun的rle
解决方案:
RLE_FUN <- function(x) {
x <- transform(x, ID = sequence(rle(do.call(paste, df))$lengths))
}
Ben的plyr
解决方案:
PLYR_FUN <- function(x) {
ddply(x, c("Place", "Sex", "Length"), transform, ID = seq_along(Length))
}
最后,data.table
解决方案:
DT_FUN <- function(x) {
dt <- data.table(x)
dt[, ID := seq_along(.I), by=names(dt)]
}
基准代码:
require(rbenchmark)
benchmark(d1 <- AVE_FUN(df),
d2 <- RLE_FUN(df),
d3 <- PLYR_FUN(df),
d4 <- DT_FUN(df),
replications = 5, order = "elapsed")
结果:
使用length = 1e3
(data.frame df中的行数)
# test replications elapsed relative user.self
# 2 d2 <- RLE_FUN(df) 5 0.013 1.000 0.013
# 4 d4 <- DT_FUN(df) 5 0.017 1.308 0.016
# 1 d1 <- AVE_FUN(df) 5 0.052 4.000 0.052
# 3 d3 <- PLYR_FUN(df) 5 4.629 356.077 4.452
使用length = 1e4
:
# test replications elapsed relative user.self
# 4 d4 <- DT_FUN(df) 5 0.033 1.000 0.031
# 2 d2 <- RLE_FUN(df) 5 0.089 2.697 0.088
# 1 d1 <- AVE_FUN(df) 5 0.102 3.091 0.100
# 3 d3 <- PLYR_FUN(df) 5 23.103 700.091 20.659
使用length = 1e5
:
# test replications elapsed relative user.self
# 4 d4 <- DT_FUN(df) 5 0.179 1.000 0.130
# 1 d1 <- AVE_FUN(df) 5 1.001 5.592 0.940
# 2 d2 <- RLE_FUN(df) 5 1.098 6.134 1.011
# 3 d3 <- PLYR_FUN(df) 5 219.861 1228.274 147.545
观察:我注意到的趋势是,随着越来越大的数据,data.table
(毫不奇怪)做得最好(尺度非常好),而ave
和rle
非常接近第二名的竞争者(ave
比rle
更好)。不幸的是,plyr
在所有数据集上表现非常差。
注意:Ananda的解决方案提供character
输出,我在基准测试中保留了它。
答案 2 :(得分:3)
不可避免的plyr
解决方案。
获取数据:
temp <- read.table(text="
Place Sex Length
A M 32
A M 33
A F 35
A F 35
A F 35
A F 39
B M 30
B F 25
B F 28
B F 28",
header=TRUE)
加载包并执行:
library("plyr")
ddply(temp,c("Place","Sex","Length"),transform,ID=seq_along(Length))
订单已更改(如果需要,可以使用arrange()
重新排序),但变量应该是正确的:
## Place Sex Length ID
## 1 A F 35 1
## 2 A F 35 2
## 3 A F 35 3
## 4 A F 39 1
## 5 A M 32 1
## 6 A M 33 1
## 7 B F 25 1
## 8 B F 28 1
## 9 B F 28 2
## 10 B M 30 1