我有一个看起来像的数据集:
mother_id,dateOfBirth
1,1962-09-24
2,1991-02-19
3,1978-11-11
我需要从出生日期中提取构成要素(日,月,年),并将它们放在相应的列中,如下所示:
mother_id,dateOfBirth,dayOfBirth,monthOfBirth,yearOfBirth
1,1962-09-24,24,09,1962
2,1991-02-19,19,02,1991
3,1978-11-11,11,11,1978
目前,我把它编码为循环:
data <- read.csv("/home/tumaini/Desktop/IHI-Projects/Data-Linkage/matching file dss nacp.csv",stringsAsFactors = F)
dss_individuals <- read.csv("/home/tumaini/Desktop/IHI-Projects/Data-Linkage/Data/dssIndividuals.csv", stringsAsFactors = F)
lookup <- data[,c("patientid","extId")]
# remove duplicates
lookup <- lookup[!(duplicated(lookup$patientid)),]
dss_individuals$dateOfBirth <- as.character.Date(dss_individuals$dob)
dss_individuals$dayOfBirth <- 0
dss_individuals$monthOfBirth <- 0
dss_individuals$yearOfBirth <- 0
# Loop starts here
for(i in 1:nrow(dss_individuals)){ #nrow(dss_individuals)
split_list <- unlist(strsplit(dss_individuals[i,]$dateOfBirth,'[- ]'))
dss_individuals[i,]["dayOfBirth"] <- split_list[3]
dss_individuals[i,]["monthOfBirth"] <- split_list[2]
dss_individuals[i,]["yearOfBirth"] <- split_list[1]
}
这似乎有效,但由于我有40万行,因此非常慢。有没有办法让我更有效地完成这项工作?
答案 0 :(得分:3)
我比较了def finder = new FileNameFinder()
def files = finder.getFileNames 'D:\\Data', '**/*.sln'
print files
,substr
和format
的使用速度。如果变量存储为日期,lubridate
和lubridate
似乎比format
快得多。但是,如果变量存储为字符向量,则substr将是最快的。显示单次运行的结果。
substr
答案 1 :(得分:2)
不确定这是否会解决您的速度问题,但这是使用dplyr和lubridate更好的方法。一般来说,在操作data.frames时,我个人建议使用data.tables或dplyr。 Data.tables应该更快,但dplyr更冗长,我个人更喜欢,因为我发现在没有阅读它几个月后更容易拿起我的代码。
library(dplyr)
library(lubridate)
dat <- data.frame( mother_id = c(1,2,3),
dateOfBirth = ymd(c( "1962-09-24" ,"1991-02-19" ,"1978-11-11"))
)
dat %>% mutate( year = year(dateOfBirth) ,
month = month(dateOfBirth),
day = day(dateOfBirth) )
或者您可以使用mutate_each函数来保存必须多次写入变量名称(尽管您对输出变量名称的控制较少)
dat %>% mutate_each( funs(year , month , day) , dateOfBirth)
答案 2 :(得分:2)
以下是一些解决方案。这些解决方案每个(i)使用1或2行代码和(ii)返回数字年,月和日列。此外,前两个解决方案不使用包 - 第三个使用chron的month.day.year
函数。
1)POSIXlt 转换为"POSIXlt"
课程并选择部分。
lt <- as.POSIXlt(DF$dateOfBirth, origin = "1970-01-01")
transform(DF, year = lt$year + 1900, month = lt$mon + 1, day = lt$mday)
,并提供:
mother_id dateOfBirth year month day
1 1 1962-09-24 1962 9 24
2 2 1991-02-19 1991 2 19
3 3 1978-11-11 1978 11 11
2)read.table
cbind(DF, read.table(text = format(DF$dateOfBirth), sep = "-",
col.names = c("year", "month", "day")))
,并提供:
mother_id dateOfBirth year month day
1 1 1962-09-24 1962 9 24
2 2 1991-02-19 1991 2 19
3 3 1978-11-11 1978 11 11
3)chron :: month.day.year
library(chron)
cbind(DF, month.day.year(DF$dateOfBirth))
,并提供:
mother_id dateOfBirth month day year
1 1 1962-09-24 9 24 1962
2 2 1991-02-19 2 19 1991
3 3 1978-11-11 11 11 1978
注1:通常在数据中添加年,月,日时,实际上并不是必需的,实际上可以在需要时使用format
substr
动态生成它们。 1}}或as.POSIXlt
因此您可能会批判性地检查您是否确实需要这样做。
注2:可重复形式的输入数据框DF
被假定为:
Lines <- "mother_id,dateOfBirth
1,1962-09-24
2,1991-02-19
3,1978-11-11"
DF <- read.csv(text = Lines)
答案 3 :(得分:1)
每个部分使用format
一次:
dss_individuals$dayOfBirth <- format(dss_individuals$dateOfBirth,"%d")
dss_individuals$monthOfBirth <- format(dss_individuals$dateOfBirth,"%m")
dss_individuals$yearOfBirth <- format(dss_individuals$dateOfBirth,"%Y")
答案 4 :(得分:0)
检查基础包中的substr
函数(或来自nice stringr
包的其他函数)以提取字符串的不同部分。此功能可以假设日,月和年总是在同一个地方并且具有相同的长度。
strsplit
函数已进行矢量化,因此使用rbind.data.frame
将列表转换为数据框可以正常工作:
do.call(rbind.data.frame, strsplit(df$dateOfBirth, split = '-'))
需要调整结果才能使用:您可以使用do.call
或t
函数进行调整。