python - 减去列之间的日期,条件是在 Python 中仅减去同一年内的日期
问题描述
所以我正在做一个需要识别多个设备启动指标的项目。为了识别启动指标,我需要这行代码来搜索一系列中唯一日期的列表并减去具有相同年份的日期。因此,如果 SV_DATE 是 2015/03/05,代码将查看“启动日期”系列以查找该年的匹配项(例如 2015/06/22),然后减去日期。between() 函数检查结果是否在 0 到 30 天的范围内,并返回一个布尔值。最后 astype(int) 如果 True 则返回 1
当我运行代码时,我遇到了两条错误消息。由于我比较了两列,第一个错误与真值不明确有关。
def day_diff(end,start):
ed = pd.to_datetime(end)
sd = pd.to_datetime(start)
#if ed.dt.year == sd.year:
return (ed-sd).dt.days
data['AL030'] = day_diff(data['SV_DATE'],data_2.loc[(data_2['MFG'] == 'APPLE') & (pd.Series(pd.DatetimeIndex(data_2['Launch Date'])).dt.year == pd.Series(pd.DatetimeIndex(data['SV_DATE'])).dt.year), 'Launch Date']).between(0,30).astype(int)
为了让代码运行,我需要对年份进行硬编码,而不是通过日期列搜索代码。当我这样做时,代码就可以工作了。
data['AL030'] = day_diff(data['SV_DATE'],data_2.loc[(data_2['MFG'] == 'APPLE') & (pd.Series(pd.DatetimeIndex(data_2['Launch Date'])).dt.year == 2017), 'Launch Date'].apply(lambda x:x.date().strftime('%Y-%m-%d'))).between(0,30).astype(int)
我什至在添加 unique() 函数之前就收到了这个错误,这给了我一个新错误:'ValueError: cannot add indices of unequal length'
data['AL030'] = day_diff(data['SV_DATE'],data_2.loc[(data_2['MFG'] == 'APPLE') & (pd.Series(pd.DatetimeIndex(data_2['Launch Date'])).dt.year == 2017), 'Launch Date'].apply(lambda x:x.date().strftime('%Y-%m-%d')).unique()).between(0,30).astype(int)
如果我不想比较列之间的年份,那么这段代码就足够了:
data['AL030'] = day_diff(data['SV_DATE'],data_2.loc[(data_2['MFG'] == 'APPLE'), 'Launch Date']).between(0,60).astype(int)
归根结底,我正在尝试优化 R 中的这段代码以返回相同的值,而不使用像这样的 launch.ind 函数,同时双重添加年份条件以尝试减少运行时间:
day_diff = function(end,start){
x = difftime(end,start,units=c("days"))
return(x)
}
launch.ind = function(ship.date,launch.date,low,high){
y = rep(0,length(data$SV_DATE))
for (i in seq(length(data$SV_DATE))){
y[i] = sum(ifelse((day_diff(ship.date[i],launch.date)>=low)&(day_diff(ship.date[i],launch.date)<=high),1,0))
y[i] = ifelse(y[i] > 0, 1, 0)
}
return(y)
}
###############################
# Add launch indicators
data$AL030 = launch.ind(data$SV_DATE,unique(data_2$"Launch Date"[toupper(data_2$MFG)=="APPLE"]),0,30)
我感谢任何试图提供帮助的人,我愿意接受帮助澄清任何不清楚的建议
解决方案
Python
假数据:
import pandas as pd
data_1 = pd.DataFrame({
'SV_DATE': pd.to_datetime(['2015/03/05', '2015/03/10', '2016/01/01'])
})
data_2 = pd.DataFrame({
'Launch Date': pd.to_datetime(['2015/03/05', '2015/12/01', '2016/01/01', '2017/01/01']),
'MFG': ['APPLE', 'WINDOWS', 'APPLE', 'WINDOWS']
})
print(data_1)
SV_DATE
0 2015-03-05
1 2015-03-10
2 2016-01-01
print(data_2)
Launch Date MFG
0 2015-03-05 APPLE
1 2015-12-01 WINDOWS
2 2016-01-01 APPLE
3 2017-01-01 WINDOWS
如果我做对了,您可以合并过滤器 data_2(仅带有 的行MFG==APPLE
),按年份合并两个数据框,按年份计算日期之间的差异,然后验证它们是否在您想要的范围内(0,30)
:
data_1 = data_1.assign(Year = data_1.SV_DATE.dt.year, Index = data_1.index)
data_2 = data_2.assign(Year = data_2['Launch Date'].dt.year).query('MFG=="APPLE"')
data = data_1.merge(data_2, on='Year')
data['Diff'] = data.groupby('Year')[['Launch Date','SV_DATE']].transform('diff', axis=1)['SV_DATE'].dt.days
data['in_target_range'] = data.Diff.between(0,30)
输出:
SV_DATE Year Index Launch Date MFG Diff in_target_range
0 2015-03-05 2015 0 2015-03-05 APPLE 0 True
1 2015-03-10 2015 1 2015-03-05 APPLE 5 True
2 2016-01-01 2016 2 2016-01-01 APPLE 0 True
我想,有了这个输出,你可以做任何你想做的事情。data_1
请注意,如果您愿意,我保留了索引列以便检索这些行。
R
使用 R 的类似方法:
library(dplyr)
# Fake data
data_1 <- data.frame(SV_DATE = as.Date(c('2015/03/05', '2015/03/10', '2016/01/01')))
data_2 <- data.frame (
Launch_Date = as.Date(c('2015/03/05', '2015/12/01', '2016/01/01', '2017/01/01')),
MFG = c('APPLE', 'WINDOWS', 'APPLE', 'WINDOWS')
)
# Merge and filters
data_2 <- data_2 %>%
mutate(Year = format(Launch_Date, "%Y")) %>%
filter(MFG=="APPLE")
data <- data_1 %>%
mutate(Year = format(SV_DATE, "%Y"), Index = 1:nrow(.)) %>%
inner_join(., mutate(data_2, Year=format(Launch_Date, "%Y")), by = "Year") %>%
group_by(Year) %>%
mutate(Diff = as.integer(SV_DATE - Launch_Date)) %>%
mutate(in_target_range = between(Diff, 0, 30))
输出是:
# A tibble: 3 x 7
# Groups: Year [2]
SV_DATE Year Index Launch_Date MFG Diff in_target_range
<date> <chr> <int> <date> <chr> <int> <lgl>
1 2015-03-05 2015 1 2015-03-05 APPLE 0 TRUE
2 2015-03-10 2015 2 2015-03-05 APPLE 5 TRUE
3 2016-01-01 2016 3 2016-01-01 APPLE 0 TRUE
我不知道你真正想要的launch.ind
功能是什么,但它可能是这样的(?):
low = 0
high = 3
data$AL030 <- data %>%
group_by(SV_DATE) %>%
summarise(launch.ind = sum(ifelse(between(Diff, low, high), 1, 0)), .groups='drop') %>%
mutate(launch.ind = ifelse(launch.ind > 0, 1, 0)) %>%
pull(launch.ind)
笔记
尽管此代码适用于我提供的虚假数据,但它可能不适用于您。无论如何,我相信它提供了一些通过修改它来实现你的目标的方法。
另外,请注意,我在两个代码块中都保留为布尔值,但您可以分别使用 Python 和 R轻松in_target_range
地将其更改为整数。.astype(int)
as.integer(...)
推荐阅读
- prolog - Prolog 多个统一到一个变量
- python - 在新文件到达 AWS S3 时触发 AWS Lambda
- python - 不确定我的自动编码器神经网络从 Keras 预测中给我的结果
- elasticsearch - ElasticSearch 失败并出现 OutOfMemoryError
- video - 如何在 FFMpeg 中连接两个或多个具有不同帧速率的视频?
- c# - 在机器人中获取 Skype 语音笔记
- javascript - 如何在 UIwebview 内的文本字段中使用变量设置值
- angular - 从 angular7 中的 api 响应创建动态表单
- hl7-fhir - 在“id”数据类型中允许下划线
- docker - 在 Docker 中组合了 `host` 和 `link` 网络