我最近发布的这个问题已经与我在我的笔记本电脑上本地使用的Mysql数据库有关。由于我没有在Mysql中找到问题的解决方案,而其他人似乎没有找到一个,我想再次发布但现在与R相关。我使用带有“RMysql”包的数据库。这是问题所在:
我有一个数据库表,其中包含几年来在几个领域的不同农业实践的数据。农民根据某项活动的日期输入信息。简化示例如下所示,其中ID是自动增量值。
ID|Field|Date |Activity |
1|A |2012/08/01|Tillage |
2|A |2012/08/24|Seeding |
3|A |2013/03/05|Spraying |
4|A |2013/03/05|Fertilizer|
5|A |2013/07/25|Harvest |
6|B |2012/09/01|Tillage |
7|B |2012/09/05|Seeding |
8|B |2013/04/05|Spraying |
9|B |2013/07/28|Harvest |
10|B |2010/08/24|Tillage |
11|B |2010/09/29|Seeding |
12|B |2011/05/01|Fertilizer|
13|B |2011/07/12|Harvest |
14|A |2011/09/01|Seeding |
15|A |2011/10/10|Spraying |
16|A |2012/04/10|Fertilizer|
17|A |2012/08/02|Harvest |
现在我想添加一个名为“季节”的列,其中仅包含收获字段的年份,但会针对各个字段的最后一次收获和此收获之间的所有其他活动自动更新。请注意,收获日期对于不同的领域是不同的。另一点是播种可能在2011年完成但是该领域在2012年收获,所有这些应该被称为2012年。在这个例子中,输出理想地看起来像: p>
ID|Field|Date |Activity |Season
1|A |2012/08/01|Tillage |2013
2|A |2012/08/24|Seeding |2013
3|A |2013/03/05|Spraying |2013
4|A |2013/03/05|Fertilizer|2013
5|A |2013/07/25|Harvest |2013
6|B |2012/09/01|Tillage |2013
7|B |2012/09/05|Seeding |2013
8|B |2013/04/05|Spraying |2013
9|B |2013/07/28|Harvest |2013
10|B |2010/08/24|Tillage |2011
11|B |2010/09/29|Seeding |2011
12|B |2011/05/01|Fertilizer|2011
13|B |2011/07/12|Harvest |2011
14|A |2011/09/01|Seeding |2012
15|A |2011/10/10|Spraying |2012
16|A |2012/04/10|Fertilizer|2012
17|A |2012/08/02|Harvest |2012
有人可以帮忙吗?
修改
如果我开始记录更多信息并将所有“活动”分别列为一个列,我需要更改哪些内容? 我试过了:
DF <- read.table(text="ID|Field|Date |Tillage|Seeding|Fertilizer|Spraying|Harvest
1|A |2012/08/01|Plough |NA|NA|NA|NA
2|A |2012/08/24|NA |Wheat|NA|NA|NA
3|A |2013/03/05|NA |NA|NA|ProduktA|NA
4|A |2013/03/05|NA|NA|TypeB|NA|NA
5|A |2013/07/25|NA |NA|NA|NA|9t
6|B |2012/09/01|Plough |NA|NA|NA|NA
7|B |2012/09/05|NA |Barley|NA|NA|NA
8|B |2013/04/05|NA |NA|NA|ProductB|NA
9|B |2013/07/28|NA |NA|NA|NA|10t
10|B |2010/08/24|Cultivator |NA|NA|NA|NA
11|B |2010/09/29|NA |NA|NA|NA|NA
12|B |2011/05/01|NA|NA|TypeB|NA|NA
13|B |2011/07/12|NA |NA|NA|NA|6t
14|A |2011/09/01|NA |Barley|NA|NA|NA
15|A |2011/10/10|NA |NA|NA|ProductC|NA
16|A |2012/04/10|NA|NA|TypeA|NA|NA
17|A |2012/08/02|NA |NA|NA|NA|7t|",
sep="|", header=TRUE, stringsAsFactors=FALSE)
DT <- data.table(DF)
DT[, Harvest:=gsub(" ", "", Harvest, fixed=TRUE)]
DT[, Date:=as.POSIXct(Date)]
setkeyv(DT, c("Field", "Date"))
DT[, Season:=cumsum(c("", !is.na(head(Harvest, -1)))), by=Field]
DT[, Season:=max(year(Date)), by=list(Field, Season)]
遗憾的是,这不起作用。有人也能解决这个问题吗?
答案 0 :(得分:2)
假设每个赛季的每个赛季都有收获(这是一个危险的假设,但我认为没办法这样做):
DF <- read.table(text="ID|Field|Date |Activity |
1|A |2012/08/01|Tillage |
2|A |2012/08/24|Seeding |
3|A |2013/03/05|Spraying |
4|A |2013/03/05|Fertilizer|
5|A |2013/07/25|Harvest |
6|B |2012/09/01|Tillage |
7|B |2012/09/05|Seeding |
8|B |2013/04/05|Spraying |
9|B |2013/07/28|Harvest |
10|B |2010/08/24|Tillage |
11|B |2010/09/29|Seeding |
12|B |2011/05/01|Fertilizer|
13|B |2011/07/12|Harvest |
14|A |2011/09/01|Seeding |
15|A |2011/10/10|Spraying |
16|A |2012/04/10|Fertilizer|
17|A |2012/08/02|Harvest |",
sep="|", header=TRUE, stringsAsFactors=FALSE)
library(data.table)
DT <- data.table(DF[, 1:4])
DT[, Activity:=gsub(" ", "", Activity, fixed=TRUE)]
DT[, Date:=as.POSIXct(Date)]
setkeyv(DT, c("Field", "Date"))
DT[, Season:=cumsum(c("", head(Activity, -1)) == "Harvest"), by=Field]
DT[, Season:=max(year(Date)), by=list(Field, Season)]
# ID Field Date Activity Season
# 1: 14 A 2011-09-01 Seeding 2012
# 2: 15 A 2011-10-10 Spraying 2012
# 3: 16 A 2012-04-10 Fertilizer 2012
# 4: 1 A 2012-08-01 Tillage 2012
# 5: 17 A 2012-08-02 Harvest 2012
# 6: 2 A 2012-08-24 Seeding 2013
# 7: 3 A 2013-03-05 Spraying 2013
# 8: 4 A 2013-03-05 Fertilizer 2013
# 9: 5 A 2013-07-25 Harvest 2013
# 10: 10 B 2010-08-24 Tillage 2011
# 11: 11 B 2010-09-29 Seeding 2011
# 12: 12 B 2011-05-01 Fertilizer 2011
# 13: 13 B 2011-07-12 Harvest 2011
# 14: 6 B 2012-09-01 Tillage 2013
# 15: 7 B 2012-09-05 Seeding 2013
# 16: 8 B 2013-04-05 Spraying 2013
# 17: 9 B 2013-07-28 Harvest 2013
PS:我认为通过滚动连接也应该可以(并且更有效),但是不能立即看到如何做到这一点。
答案 1 :(得分:0)
(MSSQL)
如果我理解你的问题,这应该有效。 相应地更改列。
SELECT DayName,CONVERT (DATE, Date) AS 'DATE' , 'DAY' =(SELECT TOP 1 DY.Date FROM
Dates DY Where DY.DayName IN (DA.DayName) Order by DY.Date Desc )FROM
Dates DA
我在db中尝试了相同的场景。
DayName DATE DAY
Date Not Supplied 1792-09-22 1792-09-22 00:00:00.000
Friday 04 January 1980 31 December 2100
Monday 09 November 2071 27 December 2100
Friday 18 January 1980 31 December 2100
答案 2 :(得分:0)
(R)
您似乎隐含地依赖这些数据行的顺序,因为字段“A”有两个不同的序列,唯一的指示是插入字段“B”记录。
dfrm <- read.table(text="ID|Field|Date |Activity |
1|A |2012/08/01|Tillage |
2|A |2012/08/24|Seeding |
3|A |2013/03/05|Spraying |
4|A |2013/03/05|Fertilizer|
5|A |2013/07/25|Harvest |
6|B |2012/09/01|Tillage |
7|B |2012/09/05|Seeding |
8|B |2013/04/05|Spraying |
9|B |2013/07/28|Harvest |
10|B |2010/08/24|Tillage |
11|B |2010/09/29|Seeding |
12|B |2011/05/01|Fertilizer|
13|B |2011/07/12|Harvest |
14|A |2011/09/01|Seeding |
15|A |2011/10/10|Spraying |
16|A |2012/04/10|Fertilizer|
17|A |2012/08/02|Harvest |",
header=TRUE, sep="|",
colClasses=c("numeric","character","Date", "character", "NULL"),
stringsAsFactors=FALSE)
dfrm$SeqID <- cumsum( c(0, dfrm$Field[-1] != head(dfrm$Field, -1) ) )
这将为您提供序列中的最后一年:
dfrm$Season <- with( dfrm, format( ave(Date, SeqID, FUN= max) , "%Y") )
> dfrm
ID Field Date Activity Season SeqID
1 1 A 2012-08-01 Tillage 2013 0
2 2 A 2012-08-24 Seeding 2013 0
3 3 A 2013-03-05 Spraying 2013 0
4 4 A 2013-03-05 Fertilizer 2013 0
5 5 A 2013-07-25 Harvest 2013 0
6 6 B 2012-09-01 Tillage 2013 1
7 7 B 2012-09-05 Seeding 2013 1
8 8 B 2013-04-05 Spraying 2013 1
9 9 B 2013-07-28 Harvest 2013 1
10 10 B 2010-08-24 Tillage 2013 1
11 11 B 2010-09-29 Seeding 2013 1
12 12 B 2011-05-01 Fertilizer 2013 1
13 13 B 2011-07-12 Harvest 2013 1
14 14 A 2011-09-01 Seeding 2012 2
15 15 A 2011-10-10 Spraying 2012 2
16 16 A 2012-04-10 Fertilizer 2012 2
17 17 A 2012-08-02 Harvest 2012 2
R data.frames通常不会以“bars”作为分隔符显示,但如果您想输出这样的对象,可以使用write.table
和sep =“|”。
write.table(dfrm, file="", sep="|", quote=FALSE,
row.names=sprintf("%3s" ,rownames(dfrm)))
ID|Field|Date|Activity|Season|SeqID
1|1|A |2012-08-01|Tillage |2013|0
2|2|A |2012-08-24|Seeding |2013|0
3|3|A |2013-03-05|Spraying |2013|0
4|4|A |2013-03-05|Fertilizer|2013|0
5|5|A |2013-07-25|Harvest |2013|0
6|6|B |2012-09-01|Tillage |2013|1
7|7|B |2012-09-05|Seeding |2013|1
8|8|B |2013-04-05|Spraying |2013|1
9|9|B |2013-07-28|Harvest |2013|1
10|10|B |2010-08-24|Tillage |2013|1
11|11|B |2010-09-29|Seeding |2013|1
12|12|B |2011-05-01|Fertilizer|2013|1
13|13|B |2011-07-12|Harvest |2013|1
14|14|A |2011-09-01|Seeding |2012|2
15|15|A |2011-10-10|Spraying |2012|2
16|16|A |2012-04-10|Fertilizer|2012|2
17|17|A |2012-08-02|Harvest |2012|2
在没有特定需要的情况下
答案 3 :(得分:0)
偶然的机会,我遇到了这个问题,我想知道为什么没有人建议 NOCB(Next Observation Carried Backward)方法,可以使用na.locf()
函数轻松实现zoo
包裹:
library(data.table)
setDT(DF)[Activity == "Harvest", Season := year(Date)][]
DF[, Season := zoo::na.locf0(Season, fromLast = TRUE)][]
ID Field Date Activity Season 1: 1 A 2012/08/01 Tillage 2013 2: 2 A 2012/08/24 Seeding 2013 3: 3 A 2013/03/05 Spraying 2013 4: 4 A 2013/03/05 Fertilizer 2013 5: 5 A 2013/07/25 Harvest 2013 6: 6 B 2012/09/01 Tillage 2013 7: 7 B 2012/09/05 Seeding 2013 8: 8 B 2013/04/05 Spraying 2013 9: 9 B 2013/07/28 Harvest 2013 10: 10 B 2010/08/24 Tillage 2011 11: 11 B 2010/09/29 Seeding 2011 12: 12 B 2011/05/01 Fertilizer 2011 13: 13 B 2011/07/12 Harvest 2011 14: 14 A 2011/09/01 Seeding 2012 15: 15 A 2011/10/10 Spraying 2012 16: 16 A 2012/04/10 Fertilizer 2012 17: 17 A 2012/08/02 Harvest 2012
从版本1.9.2开始(2014年2月27日CRAN上),data.table
已经获得了滚动连接的功能。
这里,首先创建一个带有收获日期和Season
的辅助数据表
DF[Activity == "Harvest", .(Date, Season = year(Date))]
Date Season 1: 2013/07/25 2013 2: 2013/07/28 2013 3: 2011/07/12 2011 4: 2012/08/02 2012
然后与DF
DF[Activity == "Harvest", .(Field, Date, Season = year(Date))][
DF, on = .(Field, Date), roll = -Inf]
Field Date Season ID Activity 1: A 2012/08/01 2012 1 Tillage 2: A 2012/08/24 2013 2 Seeding 3: A 2013/03/05 2013 3 Spraying 4: A 2013/03/05 2013 4 Fertilizer 5: A 2013/07/25 2013 5 Harvest 6: B 2012/09/01 2013 6 Tillage 7: B 2012/09/05 2013 7 Seeding 8: B 2013/04/05 2013 8 Spraying 9: B 2013/07/28 2013 9 Harvest 10: B 2010/08/24 2011 10 Tillage 11: B 2010/09/29 2011 11 Seeding 12: B 2011/05/01 2011 12 Fertilizer 13: B 2011/07/12 2011 13 Harvest 14: A 2011/09/01 2012 14 Seeding 15: A 2011/10/10 2012 15 Spraying 16: A 2012/04/10 2012 16 Fertilizer 17: A 2012/08/02 2012 17 Harvest
请注意,滚动连接在样本数据集中存在缺陷,其他方法未检测到 。第1行显示Season
2012虽然随后的收获(根据OP的ID
)应该是在2013年。原因是耕作和收获的日期是字段A
的混合。第1行中A栏的耕作日期是2012/08/01,而第17行中相同栏位的收获日期是2012/08/02,耕作后一天。
请注意,这两种方法都依赖于隐含的假设,即对行进行排序,使得每个Field
和Season
最后Activity
为Harvest
。否则,DF
需要使用order(Field, Date)
进行相应的排序。
library(data.table)
DF <- fread(
"ID|Field|Date |Activity |
1|A |2012/08/01|Tillage |
2|A |2012/08/24|Seeding |
3|A |2013/03/05|Spraying |
4|A |2013/03/05|Fertilizer|
5|A |2013/07/25|Harvest |
6|B |2012/09/01|Tillage |
7|B |2012/09/05|Seeding |
8|B |2013/04/05|Spraying |
9|B |2013/07/28|Harvest |
10|B |2010/08/24|Tillage |
11|B |2010/09/29|Seeding |
12|B |2011/05/01|Fertilizer|
13|B |2011/07/12|Harvest |
14|A |2011/09/01|Seeding |
15|A |2011/10/10|Spraying |
16|A |2012/04/10|Fertilizer|
17|A |2012/08/02|Harvest |", drop = 5L)