data.frame中的子集特定日期(年和月)

data.frame中的子集特定日期(年和月),r,dataframe,subset,lubridate,R,Dataframe,Subset,Lubridate,这里是我的data.frame: df = read.table(text = 'ID Date 1 1975-01-01 2 1980-02-01 3 1985-05-01 4 1990-07-01 5 1990-08-01 6 1993-01-01 7 1993-09-01', header = TRUE) 我需要通过选择特定日期(年和月)从中创建一个子集 我感兴趣的日期是: dates = c('1980-02',

这里是我的data.frame:

df = read.table(text = 'ID   Date
1      1975-01-01
2      1980-02-01
3      1985-05-01
4      1990-07-01
5      1990-08-01
6      1993-01-01
7      1993-09-01', header = TRUE)
我需要通过选择特定日期(年和月)从中创建一个子集

我感兴趣的日期是:

dates = c('1980-02', '1990-07', '1993-09')
因此,我的输出应该是:

ID     Date
2      1980-02-01
4      1990-07-01
7      1993-09-01
是否有可能编写一个独特的代码,从
df
dates
开始,而不在代码中手动添加日期

谢谢

####更新 如果我在同一个月内在
df
内得到多个观察结果,比如:

df2 = read.table(text = 'ID   Date
1      1975-01-01
2      1980-02-01
9      1980-02-01
3      1985-05-01
4      1990-07-01
12     1990-07-01
16     1990-07-01
5      1990-08-01
6      1993-01-01
7      1993-09-01
67     1993-09-01', header = TRUE)
新产出:

ID     Date
2      1980-02-01
9      1980-02-01
4      1990-07-01
12     1990-07-01
16     1990-07-01
7      1993-09-01
67     1993-09-01

谢谢

根据您共享的数据,
Date
列的类别为factor。我们将它们转换为
Date
类,提取月份和年份部分,并将其与
dates
向量匹配,以从
df
中获得匹配的行号

df[match(dates, format(as.Date(df$Date), "%Y-%m")), ]  

#   ID       Date
#2  2 1980-02-01
#4  4 1990-07-01
#7  7 1993-09-01
根据更新的问题,如果我们有多个日期要匹配,我们可以在%中使用
%这将为您提供所需的输出

df2[format(as.Date(df2$Date), "%Y-%m") %in% dates, ]

#   ID       Date
#2   2 1980-02-01
#3   9 1980-02-01
#5   4 1990-07-01
#6  12 1990-07-01
#7  16 1990-07-01
#10  7 1993-09-01
#11 67 1993-09-01

根据您共享的数据,
Date
列的类别为factor。我们将它们转换为
Date
类,提取月份和年份部分,并将其与
dates
向量匹配,以从
df
中获得匹配的行号

df[match(dates, format(as.Date(df$Date), "%Y-%m")), ]  

#   ID       Date
#2  2 1980-02-01
#4  4 1990-07-01
#7  7 1993-09-01
根据更新的问题,如果我们有多个日期要匹配,我们可以在%
中使用
%这将为您提供所需的输出

df2[format(as.Date(df2$Date), "%Y-%m") %in% dates, ]

#   ID       Date
#2   2 1980-02-01
#3   9 1980-02-01
#5   4 1990-07-01
#6  12 1990-07-01
#7  16 1990-07-01
#10  7 1993-09-01
#11 67 1993-09-01
试一试

试一试


正如@eipi10在评论中指出的那样:

df[df$Date %in% as.Date(paste0(dates,"-01")), ]
这对我更新的问题很有效


正如@eipi10在评论中指出的那样,谢谢你:

df[df$Date %in% as.Date(paste0(dates,"-01")), ]
这对我更新的问题很有效


谢谢

以下是一些解决方案。它们(i)处理任何日期,而不仅仅是一个月的第一个日期,(ii)在输出中保留
df2
的顺序,(iii)紧凑,即每行一行,不需要多次提及
df2

1)substr这不使用包

subset(df2, substr(Date, 1, 7) %in% dates)
给予:

   ID       Date
2   2 1980-02-01
3   9 1980-02-01
5   4 1990-07-01
6  12 1990-07-01
7  16 1990-07-01
10  7 1993-09-01
11 67 1993-09-01
2)zoo::as.yearmon另一种可能是将
日期和
日期转换为
“yearmon”
类,得到相同的结果。这段代码稍微好一点,但确实需要一个包

library(zoo)
subset(df2, as.yearmon(Date) %in% as.yearmon(dates))

这里有一些解决方案。它们(i)处理任何日期,而不仅仅是一个月的第一个日期,(ii)在输出中保留
df2
的顺序,(iii)紧凑,即每行一行,不需要多次提及
df2

1)substr这不使用包

subset(df2, substr(Date, 1, 7) %in% dates)
给予:

   ID       Date
2   2 1980-02-01
3   9 1980-02-01
5   4 1990-07-01
6  12 1990-07-01
7  16 1990-07-01
10  7 1993-09-01
11 67 1993-09-01
2)zoo::as.yearmon另一种可能是将
日期和
日期转换为
“yearmon”
类,得到相同的结果。这段代码稍微好一点,但确实需要一个包

library(zoo)
subset(df2, as.yearmon(Date) %in% as.yearmon(dates))

您的日期格式为字符串,因此使用它们有些困难。一般来说,最好将它们格式化为实际的日期对象。这可以通过使用。这是我要做的。我使用readr包进行自动类型检测,使用purr进行函数式编程

library(pacman)
p_load(lubridate, readr, purrr)

df = read_table(
'ID   Date
1      1975-01-01
2      1980-02-01
9      1980-02-01
3      1985-05-01
4      1990-07-01
12     1990-07-01
16     1990-07-01
5      1990-08-01
6      1993-01-01
7      1993-09-01
67     1993-09-01'
)

dates = parse_date_time(c('1980-02', '1990-07', '1993-09'), orders = "Y-m")

#subset
df[year(df$Date) %in% year(dates) & month(df$Date) %in% month(dates), ]
其输出为:

# A tibble: 7 × 2
     ID       Date
  <int>     <date>
1     2 1980-02-01
2     9 1980-02-01
3     4 1990-07-01
4    12 1990-07-01
5    16 1990-07-01
6     7 1993-09-01
7    67 1993-09-01
其输出相同:

# A tibble: 7 × 2
     ID       Date
  <int>     <date>
1     2 1980-02-01
2     9 1980-02-01
3     4 1990-07-01
4    12 1990-07-01
5    16 1990-07-01
6     7 1993-09-01
7    67 1993-09-01
#一个tible:7×2
身份证日期
1     2 1980-02-01
2     9 1980-02-01
3     4 1990-07-01
4    12 1990-07-01
5    16 1990-07-01
6     7 1993-09-01
7    67 1993-09-01

该函数所做的是在数据框中的每个日期上循环,并在每年/每月的组合上循环。然后检查年份和月份是否匹配该特定组合。如果三个组合中的任何一个匹配(因此为
any
),它将返回该行的
TRUE

您的日期被格式化为字符串,因此使用它们有些困难。一般来说,最好将它们格式化为实际的日期对象。这可以通过使用。这是我要做的。我使用readr包进行自动类型检测,使用purr进行函数式编程

library(pacman)
p_load(lubridate, readr, purrr)

df = read_table(
'ID   Date
1      1975-01-01
2      1980-02-01
9      1980-02-01
3      1985-05-01
4      1990-07-01
12     1990-07-01
16     1990-07-01
5      1990-08-01
6      1993-01-01
7      1993-09-01
67     1993-09-01'
)

dates = parse_date_time(c('1980-02', '1990-07', '1993-09'), orders = "Y-m")

#subset
df[year(df$Date) %in% year(dates) & month(df$Date) %in% month(dates), ]
其输出为:

# A tibble: 7 × 2
     ID       Date
  <int>     <date>
1     2 1980-02-01
2     9 1980-02-01
3     4 1990-07-01
4    12 1990-07-01
5    16 1990-07-01
6     7 1993-09-01
7    67 1993-09-01
其输出相同:

# A tibble: 7 × 2
     ID       Date
  <int>     <date>
1     2 1980-02-01
2     9 1980-02-01
3     4 1990-07-01
4    12 1990-07-01
5    16 1990-07-01
6     7 1993-09-01
7    67 1993-09-01
#一个tible:7×2
身份证日期
1     2 1980-02-01
2     9 1980-02-01
3     4 1990-07-01
4    12 1990-07-01
5    16 1990-07-01
6     7 1993-09-01
7    67 1993-09-01

该函数所做的是在数据框中的每个日期上循环,并在每年/每月的组合上循环。然后检查年份和月份是否匹配该特定组合。如果三个组合中的任何一个匹配(因此
any
),它将返回该行的
TRUE

因为您的数据看起来是标准化的,所以您可以使用
df[substr(df$Date,1,7)%in%dates,]
。但为了安全起见,最好使用正确的日期时间格式。
df[df$date%in%as.date(paste0(dates,“-01”),]
。这假设
df$Date
已经是日期格式。非常感谢大家!因为您的数据看起来是标准化的,所以您可以在%日期中使用
df[substr(df$Date,1,7)%cf
。但为了安全起见,最好使用正确的日期时间格式。
df[df$date%in%as.date(paste0(dates,“-01”),]
。这假设
df$Date
已经是日期格式。非常感谢大家!嗨,我刚更新了我的问题,你能看一下吗?谢谢,我刚刚更新了我的问题,你能看一下吗?谢谢