lubridate 在 R 中出现错误

5
我正在使用以下代码从日期(格式为dd/mm/yyyy)中获取星期几。

编辑:我已上传更相关的数据集。

df <- structure(list(Date = c("18/01/2013", "18/01/2013", "18/01/2013", 
                    "18/01/2013", "18/01/2013"), Time = c("07:25:30", "07:25:40", 
                                                          "07:25:50", "07:26:00", "07:26:10"), Axis1 = c(217L, 320L, 821L, 
                                                                                                         18L, 40L), Steps = c(6L, 7L, 5L, 1L, 1L), wday = c(7, 7, 7, 7, 7)), .Names = c("Date", "Time", "Axis1", "Steps", "wday"), row.names = 18154:18158, class = "data.frame")


library(lubridate)
df$wday = wday(df$Date)
df$wday.name = wday(df$Date, label = TRUE, abbr = TRUE)

然而,18/1是星期五,不是R所报告的星期六。

是否有任何建议来纠正这个问题?

编辑: 我尝试遵循Dirk的建议...

as.POSIXlt(df[,1])$wday

...但这仍然意味着18/1是星期六。

我的时区是GMT/UTC(英国夏令时加1),但由于我只想让R从日期列中读取(即d/m/y),我认为我不需要指定这个...

如何将正确的wday列添加到我的现有R数据框中? (如我在原始脚本中详细说明)。 我很难让建议的代码起作用,因为我给出的数据框格式不正确-抱歉。


你的时区是BST (+0100),而不是GMT/UTC (+0000)。时间区的不一致有时会导致日期或星期几出现偏差。 - Walter Tross
3个回答

6
您可以使用基础R函数完成此操作。使用您的df对象:
 R> as.POSIXlt(df[,1])$wday  
 [1] 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 
 R> weekdays(as.Date(df[,1])) 
  [1] "Friday"   "Friday"   "Friday"   "Friday"   "Friday"
  [6] "Friday"   "Friday"   "Friday"   "Friday"   "Friday" 
 [11] "Friday"   "Friday"   "Friday"   "Friday"   "Saturday"  
 [16] "Saturday" "Saturday" "Saturday" "Saturday" 
 R>     

由于时区未指定,结束时间会向周六溢出。

如果您这样做

 R> df <- data.frame(Date=seq(as.POSIXct("05:00", format="%H:%M", tz="UTC"),
 +                  as.POSIXct("23:00", format="%H:%M", tz="UTC"), by="hours"))

那么。
 R> table(weekdays(as.Date(df[,1], TZ="UTC")))

 Friday
    19
 R> 

我认为在lubridate下,周五/周六的错误可能会消失,但我倾向于使用基本的R函数来解决这个问题。

编辑:已确认。

R> lubridate::wday(as.Date(df[,1]), label=TRUE) 
 [1] Fri Fri Fri Fri Fri Fri Fri Fri Fri Fri Fri Fri Fri Fri 
[15] Fri Fri Fri Fri Fri          
Levels: Sun < Mon < Tues < Wed < Thurs < Fri < Sat  
R>

非常感谢 @Dirk Eddelbuettel。抱歉,我的原始数据框格式不正确,我仍然遇到问题。非常感谢任何帮助... - KT_1
我增加了奖金,因为即使有了我的新数据框架,我仍然在努力寻找解决方案。但是,我想感谢@Dirk Eddelbuettel迄今为止对我的问题的帮助。 - KT_1

3
我认为这里的问题很简单。'lubridate'软件包是专门用于此类工作的,但问题似乎在于理解'lubridate'函数。
导致问提出现奇怪结果的原因在于'df'中的日期没有以明确的格式(单位递减顺序)存储。这意味着当调用'wday'函数时,会应用错误的转换并误读日期。
为了解决这个问题,OP已经提出了将字符串转换为日期的想法,这完全正确。然而,'as.POSIXlt'函数是一种繁琐的工具,'lubridate'软件包已经有了答案:'dmy'函数。下面是它的工作原理:
df$wday <- wday(dmy(df$Date))
df$wday.name <- wday(dmy(df$Date), label=TRUE, abbr=TRUE)

我们在这里做的事情非常简单。首先,我们将 'df$Date' 从一组字符串转换为一组日期。 'dmy' 函数自动解析字符串,查找日期、月份和年份(因此是 d-m-y)。一旦我们将字符串格式正确,就可以正确使用 'wday' 函数。


0

我认为Dinre的答案是最简单的——相较于POSIX,我发现使用日期更少出错——但这里有一种直接的方法可以在同时使用日期和时间列的情况下获得正确的结果。

# Convert your Date variable into a proper Date class
# This is the base-R equivalent of Dinre's dmy()
df$Date2 <- as.Date(df$Date, format = "%d/%m/%Y")

# Paste it together with your Time into a POSIX variable with timezone
# I think "GB" is the correct timezone code for you, but not certain
df$datetime <- as.POSIXct(paste(df$Date2, df$Time), tz = "GB")

# Calculate weekday
wday(df$datetime, label = TRUE)

这个好处在于你可以把 df$datetime 用于几乎任何其他操作(例如图表),并得到一致的结果。如果你只需要使用日期,那么 Dinre 的答案就足够了。


这是我使用的时区缩写列表:http://en.wikipedia.org/wiki/List_of_zoneinfo_time_zones - Matt Parker
1
如果你还不熟悉的话,我建议你看看“lubridate”包,Matt。我以前一直使用基本的R函数,直到我发现了“lubridate”。它具有完全相同的功能,但是有着非常简洁的封装器,可以节省很多时间。我现在已经完全转换了,并且我衷心地推荐它。当然,基本函数也可以做同样的事情,所以输出并不会有任何不同,只是你的代码。 - Dinre
@Dinre 感谢您的建议 - 我经常使用lubridate进行更高级别的日期操作,但我仍然喜欢使用基本函数进行类型转换 - 部分原因是我想保留对%d/%m/%Y格式代码的知识,以防遇到非常复杂的情况。 - Matt Parker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接