【发布时间】:2019-08-07 02:17:10
【问题描述】:
(关于 R 中列表的问题)
我正在处理一个非常大的数据集,其中我的日期列采用以下两种形式之一:
- 日期类型 1:“MM/DD/YYYY HH:MM:SS AM”
- 日期类型 2:“MM/DD/YYYYHH:MM:SS AM - MM/DD/YYYY HH:MM:SS AM”
我需要根据(类型 2)中是否有破折号来拆分此列,并将它们放在两列(“日期 1”和“日期 2”)中。如果我遇到具有类型 1 日期的行,则日期将简单地占据“日期 1”,而“日期 2”将只是 NA。
这就是我要找的东西——转换一些看起来像这样的东西:
c(
rep("8/20/2018 9:18:45 AM", 15),
rep("8/20/2018 9:18:45 AM - 8/12/2018 9:18:45 AM", 15)
)
对此:
data.frame(
Date1 = c(rep("8/15/2018 9:18:45 AM", 15), rep("8/20/2018 9:18:45 AM", 15)),
Date2 = c(rep(NA, 15), rep("8/12/2018 9:18:45 AM", 15))
)
# output
# Date1 Date2
# 1 8/15/2018 9:18:45 AM <NA>
# 2 8/15/2018 9:18:45 AM <NA>
# 3 8/15/2018 9:18:45 AM <NA>
# 4 8/15/2018 9:18:45 AM <NA>
# 5 8/15/2018 9:18:45 AM <NA>
# 6 8/15/2018 9:18:45 AM <NA>
# 7 8/15/2018 9:18:45 AM <NA>
# 8 8/15/2018 9:18:45 AM <NA>
# 9 8/15/2018 9:18:45 AM <NA>
# 10 8/15/2018 9:18:45 AM <NA>
# 11 8/15/2018 9:18:45 AM <NA>
# 12 8/15/2018 9:18:45 AM <NA>
# 13 8/15/2018 9:18:45 AM <NA>
# 14 8/15/2018 9:18:45 AM <NA>
# 15 8/15/2018 9:18:45 AM <NA>
# 16 8/20/2018 9:18:45 AM 8/12/2018 9:18:45 AM
# 17 8/20/2018 9:18:45 AM 8/12/2018 9:18:45 AM
# 18 8/20/2018 9:18:45 AM 8/12/2018 9:18:45 AM
# 19 8/20/2018 9:18:45 AM 8/12/2018 9:18:45 AM
# 20 8/20/2018 9:18:45 AM 8/12/2018 9:18:45 AM
# 21 8/20/2018 9:18:45 AM 8/12/2018 9:18:45 AM
# 22 8/20/2018 9:18:45 AM 8/12/2018 9:18:45 AM
# 23 8/20/2018 9:18:45 AM 8/12/2018 9:18:45 AM
# 24 8/20/2018 9:18:45 AM 8/12/2018 9:18:45 AM
# 25 8/20/2018 9:18:45 AM 8/12/2018 9:18:45 AM
# 26 8/20/2018 9:18:45 AM 8/12/2018 9:18:45 AM
# 27 8/20/2018 9:18:45 AM 8/12/2018 9:18:45 AM
# 28 8/20/2018 9:18:45 AM 8/12/2018 9:18:45 AM
# 29 8/20/2018 9:18:45 AM 8/12/2018 9:18:45 AM
# 30 8/20/2018 9:18:45 AM 8/12/2018 9:18:45 AM
我希望列表的第一个子元素占据Date1 列,第二个子元素(如果存在)占据Date2 列。如果没有第二个元素,我希望Date2 行是NA。
我的第一次尝试是创建一个使用条件的新列表。如果子元素的长度只有一个,我创建第二个子元素,并将其设置为NA。
dates = c(
c(
rep("8/20/2018 9:18:45 AM", 15),
rep("8/20/2018 9:18:45 AM - 8/12/2018 9:18:45 AM", 15)
)
)
# create the date split. Split the text based on the dash
dates_split = strsplit(dates, " - ")
# note where the correct dates are. date_split[[15]] as one sub element and date_split[[16]] has two
dates_split[[15]];dates_split[[16]]
# so far so good
# create a conditional where if there is only one date (one sub element), set the second sub element to zero.
for(i in 1:length(dates_split)){
if(length(dates_split[i]) == 1){
dates_split[[i]][2] = NA
} else {}
}
# the above loop does not behave as expected. The dates_split[[16]][2] is now gone (it turned to NA)
# create a vector for Date1 and Date2
Date1 = unlist(lapply(dates_split, "[[", 1))
Date2 = unlist(lapply(dates_split, "[[", 2))
# put each date type in their appropriate column
date_df = data.frame(
Date1 = Date1,
Date2 = Date2
)
# second column is all NA's. Where did the second sub elements go?
我之前在较小数据集上的脚本做了这样的事情来解决它:
dates = strsplit(dates, " - ")
# this takes forever to do. Is there a way to do this without using a loop??
for(i in 1:nrow(dates_split)){
date_df$Date1 = dates[[i]][1]
date_df$Date2 = dates[[i]][2]
}
上面的效率不是很高。真实的数据集超过一百万行,因此加载需要很长时间。
对于如何修改此步骤,以便我为第二个子元素创建 NA 而不会无意中将所有内容变成 NA,是否有任何建议?
# create a conditional where if there is only one date (one sub element), set the second sub element to zero.
for(i in 1:length(dates_split)){
if(length(dates_split[i]) == 1){
dates_split[[i]][2] = NA
} else {}
}
# the above loop does not behave as expected. The dates_split[[16]][2] is now gone (it turned to NA)
谢谢!
【问题讨论】: