我有一个包含单列的数据框。
有620行。前31行标记为" A",接下来的31行标记为" B类和#34;等等。因此有20个班级。
我想做的事情很容易解释,但我需要帮助编码。
在第一次迭代中,我想删除与每个类的最后一行对应的所有行。也就是说,删除最后一个" A类"行,然后删除最后一个" B类行",依此类推。必须执行此迭代以及所有其他迭代,因为我打算使用新创建的数据集执行其他操作。
在第二次迭代中,我想删除与每个类的最后两行对应的所有行。因此,删除" A类"的最后两行,最后两行为" B class"等等。
在第三次迭代中,删除每个类的最后三行。等等。
在最后一次迭代中,我们删除每个类的最后30行。基本上我们每次观察只保留1行,第一行。
将这个放入R代码的快速方法是什么?我知道我需要使用for循环并仔细选择一些索引来删除,但是如何?
实施例
column
A1
A2
A3
B1
B2
B3
如果上面是我们的原始数据框,那么在第一次迭代中,我们应该留下
column
A1
A2
B1
B2
等等。
答案 0 :(得分:0)
我在这里做的很简单,使用n = 3而不是n = 31这个虚拟数据集
n <- 3
dummy <- c(rep("A", n), rep("B", n), rep("C", n))
> dummy
[1] "A" "A" "A" "B" "B" "B" "C" "C" "C"
现在,诀窍是使用布尔索引来选择每次迭代要保留的值,并将其与R将重复索引向量的特征结合起来,以便短矢量匹配更长的向量所需的时间。
此函数创建一个掩码,应该选择组中的元素
make_mask <- function(to_keep, n)
c(rep(TRUE, to_keep), rep(FALSE, n - to_keep))
它只是给你一个布尔矢量
> make_mask(2, 3)
[1] TRUE TRUE FALSE
我们可以在一个为迭代选择元素的函数中使用它:
pick_subset <- function(to_keep) dummy[make_mask(n - to_keep, n)]
现在,您可以在循环或lapply
中使用它来获取每次迭代所需的元素。
iterations <- iterations <- lapply(0:(n-1), pick_subset)
会给你这个
> iterations
[[1]]
[1] "A" "A" "A" "B" "B" "B" "C" "C" "C"
[[2]]
[1] "A" "A" "B" "B" "C" "C"
[[3]]
[1] "A" "B" "C"
如果在lapply
中使用1:n更符合您的口味,只需调整make_mask
即可进行补偿。
答案 1 :(得分:0)
dat%>%mutate(grp=sub("\\d","",column))%>%
group_by(grp)%>%
slice(-n())%>%
ungroup()%>%select(-grp)
# A tibble: 4 x 1
column
<chr>
1 A1
2 A2
3 B1
4 B2
数据:
dat=read.table(header = T,stringsAsFactors = F,text="column
A1
A2
A3
B1
B2
B3")
答案 2 :(得分:0)
还有另一种方式。假设代码全部按照您显示的方式进行分组和排序,请使用public class ClassRemove : RemoveInfinite<object>
{
public override object Remove()
{
return new object();
}
}
public class ClassA : SomeBaseClass, IRemove<object>
{
private RemoveInfinite<object> removeInfinite = new ClassRemove();
public object Remove()
{
return removeInfinite.Remove();
}
public bool IsCompleted
{
get { return removeInfinite.IsCompleted; }
}
}
函数获取列中的代码数。 table
cumsum
中的每个值恰好对应于每个序列中最后一项的索引。每次循环时table
变量都会增加1。通过删除由indexes
索引的行来创建y
变量。 (indexes
未排序并不重要。)您只需使用indexes
执行所需操作即可。这是带有示例data.frame:
y
N <- 31
dat <-data.frame(x=c(rep("A",31),rep("B",31),rep("C",31),rep("D",31),rep("E",31)))
t.x <- cumsum(table(dat$x))
for (i in 1:(N-1)) {
if (i == 1){
indexes <- t.x
} else {
indexes = c(indexes,t.x-i)
}
y <- dat$x[-indexes]
print(table(y))
}
将显示每个代码的计数将根据需要减少。
print(table(y))
答案 3 :(得分:0)
因为您确切地知道每个类中有多少项以及数据中存在多少个类,所以以下简单的解决方案有效:
rm(list=ls())
library(data.table)
A = rep('A', 3)
B = rep('B', 3)
C = rep('C', 3)
val = rep(1:3, 3)
DT = data.table(class=c(A,B,C), val=val)
这个循环只是迭代了每个所谓的“类”中的项目的次数。在每次迭代中,我们使用.SD[1:(4-i)]
部分代码将越来越小的原始数据子集。一定要设置一个值(在这种情况下为4),这个值比每个类中的数字项多一个,这样就不会收到“索引超出范围错误”。很酷的部分是data.table允许我们通过分组向量(在这种情况下为“类”)来完成此操作。
for(i in 1:3) {
print(DT[, .SD[1:(4-i)], by = class]) # edit as needed to save copies
}
class val
1: A 1
2: A 2
3: A 3
4: B 1
5: B 2
6: B 3
7: C 1
8: C 2
9: C 3
class val
1: A 1
2: A 2
3: B 1
4: B 2
5: C 1
6: C 2
class val
1: A 1
2: B 1
3: C 1