Create vector through ifelse in R - r

I've got two values in my global environment associated with columns starting Priority_ one is called week and one is called rest.
Week can be any number from 01 to 52
While rest can be 2018, 2017, 2016.
I'm creating an ifelse statement that if the week is equal to 3 and the year is equal to 2017 then the vector output needs to go to year 2016 and week 52. This equals to week = 3 and rest = Priority_2017
This is the code I use to create the vector:
test<-function(year){
c(paste0(rest, seq(week, by = -1, length.out=3)),paste0(year,52))
}
Then because the year before 2017 is 2016 I enter:
test("Priority_2016")
Gives the output:
[1] "Priority_20173" "Priority_20172" "Priority_20171" "Priority_201752"
I want to add this into an ifelse statement as rest and week will change, I try and use the below code:
test<-function(year){
ifelse((rest %in% c("Priority_2018", "Priority_2017","Priority_2016") & week ==3), c(paste0(rest, seq(week, by = -1, length.out=3)),paste0(year,52)),0)
}
But when I put in:
test("Priority_2016")
this only outputs:
[1] "Priority_20173"
Please let me know if you need any more information from me.

Related

I'm trying to change a data frame variable to a factor variable but having issues

> summary(CA_extract[2])
REPORTING_YEAR
Min. :1990
1st Qu.:1995
Median :2010
Mean :2007
3rd Qu.:2017
Max. :2019
> table(CA_extract[2])
1990 1995 2000 2005 2010 2015 2016 2017 2018 2019
9081 5335 5787 5685 4888 4644 4590 4606 4581 4517
> nrow(CA_extract)
[1] 53714
> ncol(CA_extract)
[1] 20
> class(CA_extract[2])
[1] "data.frame"
> summarise(CA_extract[2])
data frame with 0 columns and 1 row
> as.factor(CA_extract[2])
REPORTING_YEAR
<NA>
Levels: c(1990, 1995, 2000, 2005, 2010, 2015, 2016, 2017, 2018, 2019)
> is.numeric(CA_extract[2])
[1] FALSE
> is.character(CA_extract[2])
[1] FALSE
> is.list(CA_extract[2])
[1] TRUE
> is.double(CA_extract[2])
[1] FALSE
> is.factor(CA_extract[2])
[1] FALSE
> is.vector(CA_extract[2])
[1] FALSE
I've been trying to figure out how to change it to a factor, from what I can tell the data should allow it to work but every time I run it I get a funky column with a stack of N/As. Any help would be great, I was able to get it to work in an isolated case but I lost the solution and I wasn't able to integrate it into a for loop.
let me know if you need more info. Dunno how to provide reproducible data without you downloading the same dataset I did. (it's publically available)
Short answer: as.factor(CA_extract[[2]])
The problem has to do with how you're referencing the column in your data frame by using only single brackets. See this answer (and the relevant section in the R documentation) for a nice explanation of the differences in indexing methods.
Using single brackets to index your data frame returns another data frame, as you saw with your test class(CA_extract[2]). Compare the outputs of str(CA_extract[2]) with str(CA_extract[[2]]) and the difference should be clear.
you missed a comma:
CA_extract[, 2] <- factor(CA_extract[, 2])
Also
CA_extract$varname <- factor(CA_extract$varname)

how to clean irregular strings & organize them into a dataframe at right column

I have two long strings that look like this in a vector:
x <- c("Job Information\n\nLocation: \n\n\nScarsdale, New York, 10583-3050, United States \n\n\n\n\n\nJob ID: \n53827738\n\n\nPosted: \nApril 22, 2020\n\n\n\n\nMin Experience: \n3-5 Years\n\n\n\n\nRequired Travel: \n0-10%",
"Job Information\n\nLocation: \n\n\nGlenview, Illinois, 60025, United States \n\n\n\n\n\nJob ID: \n53812433\n\n\nPosted: \nApril 21, 2020\n\n\n\n\nSalary: \n$110,000.00 - $170,000.00 (Yearly Salary)")
and my goal is to neatly organized them in a dataframe (output form) something like this:
#View(df)
Location Job ID Posted Min Experience Required Travel Salary
[1] Scarsdale,... 53827738 April 22... 3-5 Years 0-10% NA
[2] Glenview,... 53812433 April 21... NA NA $110,000.00 - $170,000.00 (Yearly Salary)
(...) was done to present the dataframe here neatly.
However as you see, two strings doesn't necessarily have same attibutes. Forexample, first string has Min Experience and Required Travel, but on the second string, those field don't exist, but has Salary. So this getting very tricky for me. I thought I will read between \n character but they are not set, some have two newlines, other have 4 or 5. I was wondering if someone can help me out. I will appreciate it!
We can split the string on one or more '\n' ('\n{1,}'). Remove the first word from each (which is 'Job Information') as we don't need it anywhere (x <- x[-1]). For remaining part of the string we can see that they are in pairs in the form of columnname - columnvalue. We create a dataframe from this using alternating index and bind_rows combine all of them by name.
dplyr::bind_rows(sapply(strsplit(gsub(':', '', x), '\n{1,}'), function(x) {
x <- x[-1]
setNames(as.data.frame(t(x[c(FALSE, TRUE)])), x[c(TRUE, FALSE)])
}))
# Location Job ID Posted Min Experience
#1 Scarsdale, New York, 10583-3050, United States 53827738 April 22, 2020 3-5 Years
#2 Glenview, Illinois, 60025, United States 53812433 April 21, 2020 <NA>
# Required Travel Salary
#1 0-10% <NA>
#2 <NA> $110,000.00 - $170,000.00 (Yearly Salary)

R: generate dataframe of Friday dates for the year [duplicate]

This question already has answers here:
Get Dates of a Certain Weekday from a Year in R
(3 answers)
Closed 9 years ago.
I would like to generate a dataframe that contains all the Friday dates for the whole year.
Is there a simple way to do this?
eg for December 2013: (6/12/13,13/12/13,20/12/13,27/12/13)
Thank you for your help.
I'm sure there is a simpler way, but you could brute force it easy enough:
dates <- seq.Date(as.Date("2013-01-01"),as.Date("2013-12-31"),by="1 day")
dates[weekdays(dates)=="Friday"]
dates[format(dates,"%w")==5]
Building on #Frank's good work, you can find all of any specific weekday between two dates like so:
pick.wkday <- function(selday,start,end) {
fwd.7 <- start + 0:6
first.day <- fwd.7[as.numeric(format(fwd.7,"%w"))==selday]
seq.Date(first.day,end,by="week")
}
start and end need to be Date objects, and selday is the day of the week you want (0-6 representing Sunday-Saturday).
i.e. - for the current query:
pick.wkday(5,as.Date("2013-01-01"),as.Date("2013-12-31"))
Here is a way.
d <- as.Date(1:365, origin = "2013-1-1")
d[strftime(d,"%A") == "Friday"]
Alternately, this would be a more efficient approach for generating the data for an arbitrary number of Fridays:
wk1 <- as.Date(seq(1:7), origin = "2013-1-1") # choose start date & make 7 consecutive days
wk1[weekdays(wk1) == "Friday"] # find Friday in the sequence of 7 days
seq.Date(wk1[weekdays(wk1) == "Friday"], length.out=50, by=7) # use it to generate fridays
by=7 says go to the next Friday.
length.out controls the number of Fridays to generate. One could also use to to control how many Fridays are generated (e.g. use to=as.Date("2013-12-31") instead of length.out).
Takes a year as input and returns only the fridays...
getFridays <- function(year) {
dates <- seq(as.Date(paste0(year,"-01-01")),as.Date(paste0(year,"-12-31")), by = "day")
dates[weekdays(dates) == "Friday"]
}
Example:
> getFridays(2000)
[1] "2000-01-07" "2000-01-14" "2000-01-21" "2000-01-28" "2000-02-04" "2000-02-11" "2000-02-18" "2000-02-25" "2000-03-03" "2000-03-10" "2000-03-17" "2000-03-24" "2000-03-31"
[14] "2000-04-07" "2000-04-14" "2000-04-21" "2000-04-28" "2000-05-05" "2000-05-12" "2000-05-19" "2000-05-26" "2000-06-02" "2000-06-09" "2000-06-16" "2000-06-23" "2000-06-30"
[27] "2000-07-07" "2000-07-14" "2000-07-21" "2000-07-28" "2000-08-04" "2000-08-11" "2000-08-18" "2000-08-25" "2000-09-01" "2000-09-08" "2000-09-15" "2000-09-22" "2000-09-29"
[40] "2000-10-06" "2000-10-13" "2000-10-20" "2000-10-27" "2000-11-03" "2000-11-10" "2000-11-17" "2000-11-24" "2000-12-01" "2000-12-08" "2000-12-15" "2000-12-22" "2000-12-29"
There are probably more elegant ways to do this, but here's one way to generate a vector of Fridays, given any year.
year = 2007
st <- as.POSIXlt(paste0(year, "/1/01"))
en <- as.Date(paste0(year, "/12/31"))
#get to the next Friday
skip_ahead <- 5 - st$wday
if(st$wday == 6) skip_ahead <- 6 #for Saturdays, skip 6 days ahead.
first.friday <- as.Date(st) + skip_ahead
dates <- seq(first.friday, to=en, by ="7 days")
dates
#[1] "2007-01-05" "2007-01-12" "2007-01-19" "2007-01-26"
# [5] "2007-02-02" "2007-02-09" "2007-02-16" "2007-02-23"
# [9] "2007-03-02" "2007-03-09" "2007-03-16" "2007-03-23"
I think this would be the most efficient way and would also returns all the Friday in the whole of 2013.
FirstWeek <- seq(as.Date("2013/1/1"), as.Date("2013/1/7"), "days")
seq(
FirstWeek[weekdays(FirstWeek) == "Friday"],
as.Date("2013/12/31"),
by = "week"
)

How do I change the index in a csv file to a proper time format?

I have a CSV file of 1000 daily prices
They are of this format:
1 1.6
2 2.5
3 0.2
4 ..
5 ..
6
7 ..
.
.
1700 1.3
The index is from 1:1700
But I need to specify a begin date and end date this way:
Start period is lets say, 25th january 2009
and the last 1700th value corresponds to 14th may 2013
So far Ive gotten this close to this problem:
> dseries <- ts(dseries[,1], start = ??time??, freq = 30)
How do I go about this? thanks
UPDATE:
managed to create a seperate object with dates as suggested in the answers and plotted it, but the y axis is weird, as shown in the screenshot
Something like this?
as.Date("25-01-2009",format="%d-%m-%Y") + (seq(1:1700)-1)
A better way, thanks to #AnandaMahto:
seq(as.Date("2009-01-25"), by="1 day", length.out=1700)
Plotting:
df <- data.frame(
myDate=seq(as.Date("2009-01-25"), by="1 day", length.out=1700),
myPrice=runif(1700)
)
plot(df)
R stores Date-classed objects as the integer offset from "1970-01-01" but the as.Date.numeric function needs an offset ('origin') which can be any staring date:
rDate <- as.Date.numeric(dseries[,1], origin="2009-01-24")
Testing:
> rDate <- as.Date.numeric(1:10, origin="2009-01-24")
> rDate
[1] "2009-01-25" "2009-01-26" "2009-01-27" "2009-01-28" "2009-01-29"
[6] "2009-01-30" "2009-01-31" "2009-02-01" "2009-02-02" "2009-02-03"
You didn't need to add the extension .numeric since R would automticallly seek out that function if you used the generic stem, as.Date, with an integer argument. I just put it in because as.Date.numeric has different arguments than as.Date.character.

Date sequence in R spanning B.C.E. to A.D

I would like to generate a sequence of dates from 10,000 B.C.E. to the present. This is easy for 0 C.E. (or A.D.):
ADtoNow <- seq.Date(from = as.Date("0/1/1"), to = Sys.Date(), by = "day")
But I am stumped as to how to generate dates before 0 AD. Obviously, I could do years before present but it would be nice to be able to graph something as BCE and AD.
To expand on Ricardo's suggestion, here is some testing of how things work. Or don't work for that matter.
I will repeat Joshua's warning taken from ?as.Date for future searchers in big bold letters:
"Note: Years before 1CE (aka 1AD) will probably not be handled correctly."
as.integer(as.Date("0/1/1"))
[1] -719528
as.integer(seq(as.Date("0/1/1"),length=2,by="-10000 years"))
[1] -719528 -4371953
seq(as.Date(-4371953,origin="1970-01-01"),Sys.Date(),by="1000 years")
# nonsense
[1] "0000-01-01" "'000-01-01" "(000-01-01" ")000-01-01" "*000-01-01"
[6] "+000-01-01" ",000-01-01" "-000-01-01" ".000-01-01" "/000-01-01"
[11] "0000-01-01" "1000-01-01" "2000-01-01"
> as.integer(seq(as.Date(-4371953,origin="1970-01-01"),Sys.Date(),by="1000 years"))
# also possibly nonsense
[1] -4371953 -4006710 -3641468 -3276225 -2910983 -2545740 -2180498 -1815255
[9] -1450013 -1084770 -719528 -354285 10957
Though this does seem to work for graphing somewhat:
yrs1000 <- seq(as.Date(-4371953,origin="1970-01-01"),Sys.Date(),by="1000 years")
plot(yrs1000,rep(1,length(yrs1000)),axes=FALSE,ann=FALSE)
box()
axis(2)
axis(1,at=yrs1000,labels=c(paste(seq(10000,1000,by=-1000),"BC",sep=""),"0AD","1000AD","2000AD"))
title(xlab="Year",ylab="Value")
Quite some time has gone by since this question was asked. With that time came a new R package, gregorian which can handle BCE time values in the as_gregorian method.
Here's an example of piecewise constructing a list of dates that range from -10000 BCE to the current year.
library(lubridate)
library(gregorian)
# Container for the dates
dates <- c()
starting_year <- year(now())
# Add the CE dates to the list
for (year in starting_year:0){
date <- sprintf("%s-%s-%s", year, "1", "1")
dates <- c(dates, gregorian::as_gregorian(date))
}
starting_year <- "-10000"
# Add the BCE dates to the list
for (year in starting_year:0){
start_date <- gregorian::as_gregorian("-10000-1-1")
date <- sprintf("%s-%s-%s", year, "1", "1")
dates <- c(dates, gregorian::as_gregorian(date))
}
How you use the list is up to you, just know that the relevant properties of the date objects are year and bce. For example, you can loop over list of dates, parse the year, and determine if it's BCE or not.
> gregorian_date <- gregorian::as_gregorian("-10000-1-1")
> gregorian_date$bce
[1] TRUE
> gregorian_date$year
[1] 10001
Notes on 0AD
The gregorian package assumes that when you mean Year 0, you're really talking about year 1 (shown below). I personally think an exception should be thrown, but that's the mapping users needs to keep in mind.
> gregorian::as_gregorian("0-1-1")
[1] "Monday January 1, 1 CE"
This is also the case with BCE
> gregorian::as_gregorian("-0-1-1")
[1] "Saturday January 1, 1 BCE"
As #JoshuaUlrich commented, the short answer is no.
However, you can splice out the year into a separate column and then convert to integer. Would this work for you?
The package lubridate seems to handle "negative" years ok, although it does create a year 0, which from the above comments seems to be inaccurate. Try:
library(lubridate)
start <- -10000
stop <- 2013
myrange <- NULL
for (x in start:stop) {
myrange <- c(myrange,ymd(paste0(x,'-01-01')))
}

Resources