我有一个包含85行和35列的数据框,根据年龄列进行排序,如下所示:
No Gender Age
1 F 5.8
2 F 5.9
3 F 6
4 M 6.2
5 F 7
6 F 7.2
7 M 7.4
8 M 7.8
9 M 7.9
10 M 8.1
11 F 8.3
12 F 8.6
13 M 8.9
14 M 9
15 F 9.2
16 F 9.3
我需要在不同性别中对最近年龄进行分组。如下所示:
No Gender Age
1 F 6
2 M 6.2
3 F 7.2
4 M 7.4
5 M 8.1
6 F 8.3
7 F 8.6
8 M 8.9
9 M 9
10 F 9.2
答案 0 :(得分:1)
好的,我想我得到了这个。这是非常困难的,也许其他人可以提出一个更优雅的解决方案,但这就是我得到的:
df <- data.frame(No=c(1L,2L,3L,4L,5L,6L,7L,8L,9L,10L,11L,12L,13L,14L,15L,16L),Gender=c('F','F','F','M','F','F','M','M','M','M','F','F','M','M','F','F'),Age=c(5.8,5.9,6,6.2,7,7.2,7.4,7.8,7.9,8.1,8.3,8.6,8.9,9,9.2,9.3),stringsAsFactors=F);
mls <- df$Gender=='M';
mages <- df$Age[mls];
fages <- df$Age[!mls];
fisLower <- findInterval(mages,fages);
TOL <- 1e-5;
fisClosest <- fisLower+ifelse(fisLower==0L | fisLower<length(fages) & mages-fages[replace(fisLower,fisLower==0L,NA)]>fages[fisLower+1L]-mages+TOL,1L,0L);
mis <- unname(tapply(seq_along(mages),fisClosest,function(is) is[which.min(abs(mages[is]-fages[fisClosest[is[1L]]]))]));
fis <- unique(fisClosest);
df[sort(c(which(mls)[mis],which(!mls)[fis])),];
## No Gender Age
## 3 3 F 6.0
## 4 4 M 6.2
## 6 6 F 7.2
## 7 7 M 7.4
## 10 10 M 8.1
## 11 11 F 8.3
## 12 12 F 8.6
## 13 13 M 8.9
## 14 14 M 9.0
## 15 15 F 9.2
变量说明:
df
输入data.frame。mls
&#34;男性逻辑&#34;:表示df$Gender
的哪些元素为男性的逻辑向量。mages
&#34;男性年龄&#34;:男性行的df$Age
子集。fages
&#34;女性年龄&#34;:女性行的df$Age
子集。fisLower
&#34;女性指数降低&#34;:对于mages
的每个元素,这个指针都位于女性年龄的fages
之下(或者可能是等于男性年龄。如果fages
的年龄低于mages
元素,则可能为零。因此,这个向量是&#34; parallel&#34;至mages
,意思是它的长度相同且元素彼此对应。TOL
&#34;容忍&#34;在以下声明中,这是防止虚假浮点比较错误的必要烦恼。fisClosest
&#34;女性指数最接近&#34;这是fisLower
的简单转换。基本上,如果1L
的相应元素实际上更接近fisLower
的后续元素,则必须向mages
的每个元素添加fages
( &#34; upper&#34; one)而不是fisLower
的相应元素指向的那个(&#34; lower&#34; one)。这必须针对两种情况进行:(1)fisLower
的零元素,以及(2)fisLower
的元素指向fages
的非最后元素和元素mages
实际上更接近fages
的后续元素。mis
&#34;男性指数&#34;首先,要了解fisClosest
可能包含重复,如果多个男性年龄与他们最接近的女性年龄相同,IOW没有其他女性年龄接近男性年龄,对于他们所有人。对于这些冲突中的每一个,我们必须从男性年龄组中找到最接近女性年龄的男性年龄。这需要tapply()
适合的向量聚合。我们将fisClosest
分组,将mages
索引传递给lambda,我们将which.min()
称为年龄之间的绝对差异,以获得获胜的男性年龄,并返回其索引。fis
&#34;女性指数&#34;这只是fages
中唯一的一组索引,我们需要从df
中选择;我们通过删除重复项从fisClosest
获取此内容。此时我们最终可以通过索引相应的极性,将mages
和fages
索引(mis
和fis
)转换为df
行索引mls
。在对两个索引集进行组合和排序之后,我们最终可以索引df
以获得所需的输出。
原始(不正确)解决方案
看起来你想要每个游程长度的第一行和最后一行,除了整个data.frame的第一行和最后一行。这是实现这一目标的一种方法:
df <- data.frame(No=c(1L,2L,3L,4L,5L,6L,7L,8L,9L,10L,11L,12L,13L,14L,15L,16L),Gender=c('F','F','F','M','F','F','M','M','M','M','F','F','M','M','F','F'),Age=c(5.8,5.9,6,6.2,7,7.2,7.4,7.8,7.9,8.1,8.3,8.6,8.9,9,9.2,9.3),stringsAsFactors=F);
x <- cumsum(rle(df$Gender)$lengths); df2 <- df[unique(c(rbind(c(1L,x[-length(x)]+1L),x))),];
df2 <- df2[-c(1L,nrow(df2)),]; ## remove first and last row from original data.frame
df2;
## No Gender Age
## 3 3 F 6.0
## 4 4 M 6.2
## 5 5 F 7.0
## 6 6 F 7.2
## 7 7 M 7.4
## 10 10 M 8.1
## 11 11 F 8.3
## 12 12 F 8.6
## 13 13 M 8.9
## 14 14 M 9.0
## 15 15 F 9.2
我认为你错过了预期输出中的F 7.0
行;除此之外,这将获得相同的行集。如果您想将No
修正为从1顺序,则可以运行df2$No <- seq_len(nrow(df2))
。同名的行名称(LHS上有rownames(df2)
)。