【问题标题】:subsetting closed values in a column based on binary column in a data frame by RR基于数据框中的二进制列对列中的封闭值进行子集化
【发布时间】:2016-04-14 09:45:40
【问题描述】:

我有一个包含 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

【问题讨论】:

  • 您的条件不明确。 “最近”是什么意思?
  • @Sotos:相近的年龄,例如想要 rwos 3 和 4 而不是 1 和 4。6 和 6.2 比 5.8 和 6.2 更接近。
  • 啊……好吧。我明白了
  • 我不确定我是否明白你的意思,但它像示例一样排序并且最大值并不重要,只是关闭年龄很重要。
  • 女性最大值为 13.3,男性最大值为 18.3

标签: r dataframe


【解决方案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 输入数据帧。
  • mls "malelogicals":表示df$Gender 的哪些元素是男性的逻辑向量。
  • mages“男性年龄”:df$Age 的子集,用于男性行。
  • fages“女性年龄”:df$Age 的子集,用于女性行。
  • fisLower“女性指数较低”:对于mages 的每个元素,这具有到女性年龄的fages 的索引,该女性年龄正好低于(或可能等于)男性年龄。如果fages 的年龄没有低于mages 的元素,则该值可能为零。因此,这个向量与mages“平行”,这意味着它的长度相同并且元素彼此对应。
  • TOL "tolerance" 这是防止以下语句中出现虚假浮点比较错误的必要烦恼。
  • fisClosest "女性指数最接近" 这是fisLower 的简单转换。基本上,如果mages 的对应元素实际上更接近fages后续 元素(“上”元素),我们必须将1L 添加到fisLower 的每个元素中,而不是fisLower 的对应元素指向的那个(“较低的”一个)。这必须在两种情况下完成:(1)fisLower 的零元素,以及(2)fisLower 的元素指向fages 的非最后一个元素,而mages 的元素实际上更接近到fages 的后续元素。
  • mis“男性索引”首先,了解fisClosest 可能包含重复,如果多个男性年龄与他们最接近的女性年龄相同,IOW 没有其他女性年龄更接近该男性年龄,对于所有这些男性。对于这些冲突中的每一个,我们必须从一组男性年龄中找到最接近女性年龄的一个男性年龄。这需要一个适合tapply() 的向量聚合。我们按fisClosest 分组,将mages 索引传递给lambda,我们在其中调用which.min() 以获取获胜男性年龄之间的绝对差异,并返回其索引。
  • fis "女性索引" 这只是 fages 的唯一索引集,我们需要从 df 中选择;我们通过删除重复项从fisClosest 获得此信息。

此时,我们终于可以通过索引mls 的相应极性,将magesfages 索引(misfis)转换为df 行索引。将两个索引集合并排序后,我们最终可以索引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 &lt;- seq_len(nrow(df2))。行名称同上(在 LHS 上使用 rownames(df2))。

【讨论】:

  • 感谢您的帮助,但这对我没有帮助。我需要像我写的那样的输出。只是每个性别中最接近的年龄。
  • 给你的问题:你能看看data.frame(Gender=c('F','M','M','M','F'),Age=c(5,11,12,13,14)),告诉我那个测试用例的预期输出是什么吗?
  • 结果将是:data.frame(Gender=c('M','F'),Age=c(13,14))
猜你喜欢
  • 2020-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多