Is there a way to get Tableau to recognize generic days as a time series?
I have scientific data that involves measurements taken over twelve days. It doesn't matter what those actual dates are - I don't know if it was January or October, last month or five years ago. What matters is seeing them in order from Day 1, Day 2, Day 3, and being able to use time series functionality like animation and such. My gut instinct is to give it fake dates like January 1, 2018, January 2, etc and then change the alias, but is there a more elegant solution?
Example:
Sample A
Day 1: 80
Day 2: 116
Day 3: 152
Sample B
Day 1: 30
Day 2: 65
Day 3: 189
Sample C
Day 1: 45
Day 2: 103
Day 3: 162
If it's true that the actual date doesn't matter, then the best thing to do would treat your days as a series of numbers on a timeline. Afterall, that's what Tableau does with dates. Of course, Tableau's treatment of dates isn't that simple, but for this example, we can simply treat our dates as numbers.
I went ahead and create a small data set to simulate your scenario.
In order to get the split the number out of our [day] column, we use Tableau's SPLIT function.
The delimiter is a space or " " and we want the second value returned from the split. We also want this to be an Integer, so we wrap the whole function in the INT function.
Finally, you'll be able to see those values spread across your days.
By adding our new [Day Number] to the filter you can use the slider to be selective with the days you display.
I'm assuming your Dimension of Days contains values like "Day 1", "Day 2", etc.
You can create a calculated field as follows:
case [Day]
WHEN "Day 1" THEN #2018-01-01#
WHEN "Day 2" THEN #2018-01-02#
WHEN "Day 3" THEN #2018-01-03#
WHEN "Day 4" THEN #2018-01-04#
WHEN "Day 5" THEN #2018-01-05#
WHEN "Day 6" THEN #2018-01-06#
WHEN "Day 7" THEN #2018-01-07#
WHEN "Day 8" THEN #2018-01-08#
WHEN "Day 9" THEN #2018-01-09#
WHEN "Day 10" THEN #2018-01-10#
WHEN "Day 11" THEN #2018-01-11#
WHEN "Day 12" THEN #2018-01-12#
end
Tableau uses the # around text to convert the value to a Date type.
Result:
Related
I saw the time format "0102150405" in the code, but I don't know what's the format is, Does anyone have an idea about it? 😂
time.Now().UTC().Format("0102150405")
(January 2, 15:04:05, 2006, in time zone seven hours west of GMT).
That value is recorded as the constant named Layout, listed below.
As a Unix time, this is 1136239445. Since MST is GMT-0700,
the reference would be printed by the Unix date command as:
Mon Jan 2 15:04:05 MST 2006
You can use it to format the time value you got.
0102150405 means want to format time.Now() as string like "${month}${day}${hour}${minute}${second}".
Here is a summary of the components of a layout string. Each element shows by example the formatting of an element of the reference time. Only these values are recognized. Text in the layout string that is not recognized as part of the reference time is echoed verbatim during Format and expected to appear verbatim in the input to Parse.
Year: "2006" "06"
Month: "Jan" "January" "01" "1"
Day of the week: "Mon" "Monday"
Day of the month: "2" "_2" "02"
Day of the year: "__2" "002"
Hour: "15" "3" "03" (PM or AM)
Minute: "4" "04"
Second: "5" "05"
AM/PM mark: "PM"
See more:
https://pkg.go.dev/time#pkg-constants
https://pkg.go.dev/time#Time.Format
First of all, full disclosure, I am working on a homework assignment. The example I'm giving is not the exact problem, but will help me understand what I need to do. I'm not looking for a spoon-fed answer but to understand what is going on.
I am trying to take a string such as:
"The Civil War started in 1861."
"The American Revolution started in 1775."
In this example I would like to return the same string, but with the appropriate century in parenthesis after
"The Civil War started in 1861. (Nineteenth Century)"
"The American Revolution started in 1775. (Eighteenth Century)"
I am able to group what I need using the following regex
text.gsub!(/([\w ]*)(1861|1775).?/, '\1\2 (NOT SURE HERE)')
It would be easy using grouping to say if \2 == 1861 append appropriate century, but the specifications say no if statements may be used and I am very lost. Also, the alternation I used in this example only works for the 2 years listed and I know that a better form of range-matching would have to be used to catch full centuries as opposed to those 2 single years.
Firstly - how to remove the hardcoding of the years:
text.gsub!(/([\w ]*)([012]\d{3}).?/, '\1\2 (NOT SURE HERE)')
This should handle things for the next ~1k years. If you know for a fact that the dates are restricted to given periods, you can be more specific.
For the other part - the century is just the first two digits plus one. So split the year in two and increment.
text.gsub(/[\w ]*([012]\d)\d\d.?/) do |sentence|
"#{sentence} (#{$1.next}th Century)"
end
Note the usage of String#gsub with block due to the fact that we need to perform a transformation on one of the matched groups.
Update: if you want the centuries to be in words, you could use an array to store them.
ordinals = %w(
First Second Third Fourth Fifth Sixth Seventh Eighth Ninth Tenth Eleventh
Twelfth Thirteenth Fourteenth Fifteenth Sixteenth Seventeenth Eighteenth
Nineteenth Twentieth Twenty–First
)
text.gsub(/[\w ]*([012]\d)\d\d.?/) do |sentence|
"#{sentence} (#{ordinals[$1.to_i]} Century)"
end
Update (2): Assuming you want to replace something completely different and you can't take advantage of number niceties like in the centuries example, implement the same general idea, just use a hash instead of array:
replacements = {'cat' => 'king', 'mat' => 'throne'}
"The cat sat on the mat.".gsub(/^(\w+ )(\w+)([\w ]+ )(\w+)\.$/) do
"#{$1}#{replacements[$2]}#{$3}#{replacements[$4]}."
end
Assuming the year is between 1 and 2099, you might do it as follows.
YEAR_TO_CENTURY = (1..21).to_a.zip(%w| First Second Third Fourth Fifth Sixth
Seventh Eighth Ninth Tenth Eleventh Twelfth Thriteenth Fourteenth Fifteenth
Sixteenth Seventeenth Eighteenth Nineteenth Twentieth Twentyfirst | ).to_h
#=> { 1=>"First", 2=>"Second", 3=>"Third", 4=>"Fourth", 5=>"Fifth", 6=>"Sixth",
# 7=>"Seventh", 8=>"Eighth", 9=>"Ninth", 10=>"Tenth", 11=>"Eleventh",
# 12=>"Twelfth", 13=>"Thriteenth", 14=>"Fourteenth", 15=>"Fifteenth",
# 16=>"Sixteenth", 17=>"Seventeenth", 18=>"Eighteenth", 19=>"Nineteenth",
# 20=>"Twentieth", 21=>"Twentyfirst" }
def centuryize(str)
str << " (%s Century)" % YEAR_TO_CENTURY[(str[/\d+(?=\.)/].to_i/100.0).ceil]
end
centuryize "The American Revolution started in 1775."
#=> "The American Revolution started in 1775. (Eighteenth Century)"
centuryize "The Battle of Hastings took place in 1066."
#=> "The Battle of Hastings took place in 1066. (Eleventh Century)"
centuryize "Nero played the fiddle while Rome burned in AD 64."
#=> "Nero played the fiddle while Rome burned in AD 64. (First Century)"
It would be easier if we could write "19th" century.
def centuryize(str)
century = (str[/\d+(?=\.)/].to_i/100.0).ceil
suffix =
case century
when 1, 21 then "st"
when 2 then "nd"
when 3 then "rd"
else "th"
end
"%s (%d%s Century)" % [str, century, suffix]
end
centuryize "The American Revolution started in 1775."
# => "The American Revolution started in 1775. (18th Century)"
centuryize "The Battle of Hastings took place in 1066."
#=> "The Battle of Hastings took place in 1066. (11th Century)"
centuryize "Nero played the fiddle while Rome burned in AD 64."
#=> "Nero played the fiddle while Rome burned in AD 64. (1st Century)"
I have "Content type" called Banner, it has two date fields:
ad_start
and
ad_stop
Both set to be date and time format. With ad_start default to "now" and ad_stop default set to "+7 days".
I then have a view "Frontpage Floor Banner" in which I want to have a filter in order to filter out all banners with
ad_start => "now"
and
ab_stop <= "now"
Under Configure filter criterion: Content: Start (field_ad_start), Operator has following possible options to choose from:
Is equal to
Is not equal to
Contains
Contains any word
Contains all words
Starts with
Does not start with
Ends with
Does not end with
Does not contain
Length is shorter than
Length is longer than
Regular expression
Is empty (NULL)
Is not empty (NOT NULL)
However I cant understand which Operator I can use to achieve this...
This is on 8.0.0-beta9.
Make sure to use the latest version of Drupal 8, because for a while there was no Datetime field filter for views, and it would have treated it like an integer rather than a date. In Drupal 8.0.5 (the latest as of this writing) the available operators for a core Datetime field are;
Is less than
Is less than or equal to
Is equal to
Is not equal to
Is greater than or equal to
Is greater than
Is between
Is not between
Regular expression
Is empty (NULL)
Is not empty (NOT NULL)
So for ad_start you would choose 'Is greater than or equal to' and for "Value type" choose 'An offset from the current time such as "+1 day" or "-2 hours -30 minutes"', then enter:
now
For ad_stop choose 'Is less than or equal to' and for "Value type" choose 'An offset from the current time such as "+1 day" or "-2 hours -30 minutes"', then enter:
now
view datetime field filter example
Note that the Date module is not yet available for Drupal 8, but D8 does have a (somewhat limited) core Datetime field, which is what I assume you are using.
Make sure yo enable the Date Views (date_views) module.
I'm pulling date-time strings from a large CSV file, which look like this:
"11/19/2008 21:56"
I'd like to extract the hour only, so I can build a histogram of all the hours to find the most frequent ones. Similarly, I'd like to extract days of the week (names) from the dates and build a histogram of most frequent days.
I'm new to Ruby, looked up the information, for starters tried various forms of the following, but no luck:
require 'date'
puts DateTime.strptime("11/19/2008 21:56", '%I')
Can you please advise a simple (and clear) way to accomplish the above? Also, any suggestions how to represent the results would be great. I'm thinking one hash array for the hours (24 entries) and one for the days (7 entries)? What would be the neatest algorithm to load them up as I iterate through the date-time strings, and then maybe re-sorting them with most frequent on top? Thanks!!
This is the starting point:
dt = "11/19/2008 21:56"
require 'date'
DateTime.strptime(dt, '%m/%d/%Y %H:%M') # => #<DateTime: 2008-11-19T21:56:00+00:00 ((2454790j,78960s,0n),+0s,2299161j)>
Date formats like "11/19/2008" present a problem when parsing because the default is to use this format:
'%d/%m/%Y'
Date blows up when it sees a month value of 19. '%m/%d/%Y' is not as popular around the world as '%d/%m/%Y', which is why Ruby defaults to it.
Once you have the timestamp parsed, you can easily extract parts from it:
datetime = DateTime.strptime(dt, '%m/%d/%Y %H:%M')
datetime.hour # => 21
datetime.wday # => 3
Notice that wday returns values from 0..6, not 1..7, where 0 = Sunday:
%w[Sunday Monday Tuesday Wednesday Thursday Friday Saturday][datetime.wday]
# => "Wednesday"
Rails' ActiveSupport has a lot of useful methods as part of its Date, DateTime and Time support. Using them is easy, and it's easy to cherry-pick which you want if you decide to add them to plain-ol' Ruby code.
"11/19/2008 21:56".split[1]
=> "21:56"
If can be in other formats, but always the only part with a ":" and two digits on each side, you can use
"11/19/2008 21:56"[/\d{2}:\d{2}/]
=> "21:56"
And for day, something similar
"11/19/2008 21:56"[/\d{2}\/\d{2}\/\d{4}/]
=> "11/19/2008"
I have something like this, which is in .txt format.
'random title'
random things , 00:00 AM, 1 January
2005, 555 words, (English)
'random long title'
random things , 00:00 AM, 1 January 2005, 111 words,
(English)
The time and date need to be extracted in the format yyyymmdd and hhmm.
I tried to use comma as the delimiter.
DATA News;
INFILE 'C:xxxx/xxxx/xxxx' DLM',';
INPUT Title $75. Time $10. Date $20. Words $15. Lang $10.;
PROC PRINT DATA=News;
TITLE 'Time and Date';
VAR Time Date;
RUN;
But it failed, those entries contain multiple lines and also are not well-formatted.
Are there any solutions?
If your dates are always formatted like so:
00:00 AM, 1 January 2005
Then you can use a perl regular expression to find them.
data test;
input #;
_prx = prxparse('/\d\d:\d\d (?:AM|PM), \d{1,2} (?:January|February|March) \d{4}/');
start = 1;
stop = length(_infile_);
call prxnext(_prx, start, stop, _infile_, position, length);
do while (position > 0);
found = substr(_infile_, position, length);
put found= position= length=;
call prxnext(_prx, start, stop, _infile_, position, length);
end;
datalines;
'random title'
random things , 00:00 AM, 1 January
2005, 555 words, (English)
'random long title'
random things , 00:00 AM, 1 January 2005, 111 words,
(English)
;;;;
run;
Then use the FOUND value as you would normally with a SAS character variable to obtain date and time, or datetime, information. Obviously extend my short list of months to contain all twelve months.
That finds the second example, but not the first (which is not reasonably findable using datalines in an example); but if you are not using datalines, but instead a text file, you could manipulate the record format to remove the line feed and carriage return and thus see both as a single record (and thus match). Look into RECFM=N for more details on that.