这是我第一次自己设法找到问题的解决方案,使用现有帖子中建议的R代码。所以,感谢所有帮助者,我得到了迄今为止所有的帮助。
设计:
我有一个很大的data.frame
(大约370万行×15列;让我们称之为df
)看起来像这样(为了更清楚我只保留了必要的列示例):
Site Date Type Mesure ....
1 1590041 1998-05-15 P 0.15
2 1590041 1999-05-04 P 0.18
3 1590041 2000-05-16 C 3.6
4 1590041 2001-05-15 I 2.10
5 1590041 2002-04-17 P 4.30
6 1590041 2003-09-03 I 0.20
7 1700224 1999-12-15 P 0.19
8 1700224 1999-05-08 P 2.12
9 1700224 2000-05-12 C 1.6
10 1700224 2001-05-15 I 3.10
11 1700224 2003-08-19 P 0.30
12 1700224 2003-09-03 I 2.20
....
对于每个网站,我的样本为Type = "C"
,Type = "I"
或Type = "P"
Type = "C"
就像我的数据集中的引用一样。大多数情况下,每个站点只有1个Type = "C"
样本(少数例外有2个Type = "C"
样本)。
我想为Type="C"
中的每个data.frame
样本找到最接近(使用Date
)Type="I"
和最近Type="P"
个样本的样本,但来自同一个Site
。
最终目标是通过保留所有data.frame
个样本来对我的初始Type="C"
进行子集化,但只有Type="P"
和Type="I"
个样本最接近Type="C"
来自同一站的样本。
在一位同事的帮助下,我们写道:
c1 <- df[df$Type=="C",]
p1 <- df[df$Type=="P",]
i1 <- df[df$Type=="I",]
toto <- by(df, df$Site, FUN = function(y)
t(as.data.frame(sapply(y[y$Type == "C", "Date"], function(x)
y[y$Type == "P", ][which.min(abs(difftime(x, y[y$Type == "P", "Date"]))), ]))))
head(toto)
$`1590041`
Site Date Type Mesure
V1 "1590041" 1246406400 "P" 0.18
$`1700224`
Site Date Type Mesure
V1 "1700224" 1282694400 "P" 2.12
...
然后,我重复toto2
与toto
相似但对type = "P"
更改type= "I"
的操作。
这不是我想要的,但我没有找到更接近我的期望的方法(至少,代码返回正确的Type="P"
行)。
我的问题(我不是说我希望我的代码能够产生其他东西,我想改进以下几点):
结果是一个列表(我以后仍可以rbind
)
我无法找到一种方法同时搜索最接近的Type=P
- 样本和Type=I
样本(即在单个函数中;目前,我重复相同的程序2次)
我得到了傻瓜&#34; Date
的格式,并且不明白为什么。
更重要的是:我使用此代码,通过site
询问结果。对于包含2 Type=C
个样本(少数情况)的网站,它不起作用。我更愿意询问结果Type="C"
示例,但这意味着在代码中添加一个条件,用于查看来自同一Type="P"
的{{1}}和Type="C"
个样本。
理想情况下,代码会返回如下内容:
Site
我必须承认,我已经失去了所有 Site Date Type Mesure ....
2 1590041 1999-05-04 P 0.18
3 1590041 2000-05-16 C 3.6
4 1590041 2001-05-15 I 2.10
8 1700224 1999-05-08 P 2.12
9 1700224 2000-05-12 C 1.6
10 1700224 2001-05-15 I 3.10
,(
,{
等等......
如果有人对我的大[
进行子集化并且仅保留所选行(即最接近同一data.frame
的{{1}}样本)有一些建议,我将不胜感激。
答案 0 :(得分:1)
这是dplyr
使事情变得更容易的一个很好的例子:
df <- read.table(text=" Site Date Type Mesure
1 1590041 1998-05-15 P 0.15
2 1590041 1999-05-04 P 0.18
3 1590041 2000-05-16 C 3.6
4 1590041 2001-05-15 I 2.10
5 1590041 2002-04-17 P 4.30
6 1590041 2003-09-03 I 0.20
7 1700224 1999-12-15 P 0.19
8 1700224 1999-05-08 P 2.12
9 1700224 2000-05-12 C 1.6
10 1700224 2001-05-15 I 3.10
11 1700224 2003-08-19 P 0.30
12 1700224 2003-09-03 I 2.20", stringsAsFactors=FALSE)
df$Date <- as.Date(df$Date)
library(dplyr)
df2 <- df %>% group_by(Site) %>%
mutate (Diff = abs(difftime(Date, Date[Type=="C"], units="days"))) %>%
group_by(Site, Type) %>%
filter(Diff == min(Diff)) %>%
select(-Diff)
df2
# Site Date Type Mesure
#1 1590041 1999-05-04 P 0.18
#2 1590041 2000-05-16 C 3.60
#3 1590041 2001-05-15 I 2.10
#4 1700224 1999-12-15 P 0.19 # Your expected result was wrong for this line
#5 1700224 2000-05-12 C 1.60
#6 1700224 2001-05-15 I 3.10
df2
是通过Site
对数据进行分组创建的,创建一个新的列,其中日期和日期Type == C
之间存在绝对差异,然后按Type
分组}和Date
,并仅过滤每个Type
的每个Site
的较小差异。
这并不能解决您的重复Type C
问题,因为您没有指定要选择哪一个(或至少用作参考)。如果您有该信息,则可以更新代码。例如,如果您在min(Date[Type=="C"])
内使用difftime
,则会使用最早的Date
,但您也可以使用Date[Type=="C"][1]
来选择Type C
的第一次出现。在这两种情况下,只会保留一个Type C
,以便同时调整filter
来电。
答案 1 :(得分:1)
sp <- sapply(unique(df$Site), function(X) which(df$Site == X & df$Type == 'P')
[which.min(abs(difftime(df[df$Site== X & df$Type == 'C',]$Date,
df[df$Site== X & df$Type == 'P',]$Date)))])
si <- sapply(unique(df$Site), function(X) which(df$Site == X & df$Type == 'I')
[which.min(abs(difftime(df[df$Site== X & df$Type == 'C',]$Date,
df[df$Site== X & df$Type == 'I',]$Date)))])
sc <- which(df$Site %in% unique(df$Site) & df$Type == 'C')
df[sort(c(sp, si, sc))]
# Site Date Type Mesure
#2 1590041 1999-05-04 P 0.18
#3 1590041 2000-05-16 C 3.60
#4 1590041 2001-05-15 I 2.10
#7 1700224 1999-12-15 P 0.19
#9 1700224 2000-05-12 C 1.60
#10 1700224 2001-05-15 I 3.10
sp
包含P
类型行的行号,这些行的日期为同一C
Site
的{{1}}