Change date format in Column - python

I have data with dates in columns as seen below. Dates are the headers
2020-04-14 2020-04-15 4/16/20
I would like to change 4/16/20 to read as 2020-04-16
I used:
df.loc[24,"4/16/20"] = "2020-04-16"
df
It ended up changing everything in the column and not the header
Please help!

You can use strftime to fix timestamp
import pandas as pd
data = {'col1': [1, 2, 3],
'col2': [4, 5, 6],
'col3': [7, 8, 9]}
# create headers
header = ['2020-04-14', '2020-04-15', '4/16/20']
# creating dataframe
df = pd.DataFrame(data, columns=header)
#print(df)
#converting headers to datetime format
df.columns = pd.to_datetime(df.columns)
#fixing the datetime format
df.columns = df.columns.strftime('%Y-%m-%d')
print(df)

I couldn't understand what you mean by read as 2020-04-16. Here's my solution. Hope it helps.
from datetime import datetime
# Parse the original date string using datetime.strptime
original_date = datetime.strptime("4/16/20", "%m/%d/%y")
# Convert the date to the desired format using datetime.strftime
new_date = original_date.strftime("%Y-%m-%d")
print(new_date)
Output: "2020-04-16"

According to Pandas manual, you can use build-in pd.to_datetime with infer_datetime_format parameter.
Usually datatime format is the way to go.
Since your dates are already headers, all you need to do is just to convert columns to datatime:
df.columns = pd.to_datetime(df.columns, infer_datetime_format=True)
It will be in %Y-%m-%d format by default.

Related

How to get the current date in 'YYYY-MM-DD' and 'datetime64[ns]' format?

I am trying to get the current date in 'YYYY-MM-DD' format, but it seems to be in a String format, and I want it to be in datetime64[ns] format.
So far, I have done this:
>>> import datetime
>>> from datetime import datetime
>>> todays_date = datetime.today().strftime('%Y-%m-%d')
>>> todays_date
'2022-06-06'
I have got the current date, but it is not in the format I need.
How do I convert it to datetime64[ns]?
Thanks.
If you are trying to convert your data to [ns] in pandas this will allow you to achieve the [ns] option
todays_date = datetime.datetime.today().strftime('%Y-%m-%d %X')
df = pd.DataFrame({
'Dates' : [todays_date]
})
df['Dates'] = pd.to_datetime(df['Dates'], infer_datetime_format=True)
df.dtypes
If for whatever reason you want just the date and not the time for your data you can do this to remove the hours/minutes/seconds and it will still be in [ns] format
todays_date = datetime.datetime.today().strftime('%Y-%m-%d 00:00:00')
df = pd.DataFrame({
'Dates' : [todays_date]
})
df['Dates'] = pd.to_datetime(df['Dates'], infer_datetime_format=True)
df.dtypes
pd.to_datetime("today").strftime("%Y/%m/%d")

how to sort by dates in format d-month-y in pandas?

I have a column with dates looking like this: 10-apr-18.
when I'm transposing my df or doing anything with it, pandas automatically sort this column by the day (the first number) so it's not chronological.
I've tried to use to_datetime but because the month is a string it won't work.
How can I convert this to date OR cancel the automatically sorting (my raw data is already in the right order).
I suggest convert to datetimes with to_datetime and parameter format:
df = pd.DataFrame({'dates':['10-may-18','10-apr-18']})
#also working for me
#df['dates'] = pd.to_datetime(df['dates'])
df['dates'] = pd.to_datetime(df['dates'], format='%d-%b-%y')
df = df.sort_values('dates')
df['dates'] = df['dates'].dt.strftime('%d-%B-%y')
print (df)
dates
1 10-April-18
0 10-May-18
df = pd.DataFrame({'dates':['10-may-18','10-apr-18']})
#also working for me
#df['dates'] = pd.to_datetime(df['dates'])
df['datetimes'] = pd.to_datetime(df['dates'], format='%d-%b-%y')
df = df.sort_values('datetimes')
df['full'] = df['datetimes'].dt.strftime('%d-%B-%y')
print (df)
dates datetimes full
1 10-apr-18 2018-04-10 10-April-18
0 10-may-18 2018-05-10 10-May-18
df['dates'] = pd.to_datetime(df['dates'], format='%d-%b-%y').dt.strftime('%d/%B/%y')

Pandas DateTime Format not working - python

I am trying to format some dates with datetime, but for some reason it is ignoring my format call. I want day/month/Year format which is what the CSV file has the format is, but when I try this.
df = pd.read_csv('test.csv', parse_dates=['Date'],
date_parser=lambda x: pd.to_datetime(x, format='%d/%m/%Y'))
Result:
Why is it what I can only assume "defaulting" to %Y-%m-%d ???
This should work.
import datetime as dt
import pandas as pd
df = pd.read_csv('test.csv')
formatted_dates =[]
for old_date in df['Date']:
dt_obj = dt.datetime.strptime(old_date,'%d/%m/%Y')
new_date = """{}/{}/{}""".format(dt_obj.day,dt_obj.month,dt_obj.year)
formatted_dates.append(new_date)
df['Date'] = formatted_dates
Output:
18/1/2017
22/1/2017
31/1/2017
...
P.S. There's a bug with the parse_dates,date_parser in pd.read_csv which automatically changes the format to the YYYY-MM-DD.

Pandas convert mongodb bson.tz_util.FixedOffset to standard date

I am trying to calculate offset from epoch seconds with a Pandas dataframe created from data from a mongodb document.
An example of the data layout and operation is as per below (this codes works OK)
data = {'ds': ['2018-01-13 18:47:05.069722+00:00', '2018-01-14 18:47:05.119994+00:00', '2018-01-15 18:47:05.178768+00:00'],
'y': [38, 20, 26]}
df = pd.DataFrame(data, columns = ['ds', 'y'])
df['ds'] = pd.to_datetime(df['ds'])
t = np.array(
(df['ds'] - pd.datetime(1970, 1, 1))
.dt.total_seconds()
.astype(np.float)
) / (3600 * 24.)
Note that however the dtype of the ds column in the code above is
datetime64[ns]
and the dtype of the date column from the actual pandas data in question is
datetime64[ns, <bson.tz_util.FixedOffset objec...
The only way I have been able to work out how to get around this is to convert to string then back to date:
dates = df['ds'].apply(lambda x: x.strftime('%Y-%m-%d %H:%M:%S'))
df['ds'] = pd.to_datetime(dates)
Is there a better way to convert a
datetime64[ns, <bson.tz_util.FixedOffset object
into a datetime64[ns] column type in Pandas?
This worked for me.
import pandas as pd
# have to convert the series to date index
dsIndex = pd.Index(df['ds'])
# strip off the TZ info (assume it was <bson.tz_util.FixedOffset objec...)
dsIndex = dsIndex.tz_localize(tz=None)
# Reassign it to UTC
dsUTC = dsIndex.tz_localize(tz='UTC')
import pytz
df[column] = df[column].apply(lambda x: x.astimezone(pytz.utc))
does the trick

Can pandas automatically read dates from a CSV file?

Today I was positively surprised by the fact that while reading data from a data file (for example) pandas is able to recognize types of values:
df = pandas.read_csv('test.dat', delimiter=r"\s+", names=['col1','col2','col3'])
For example it can be checked in this way:
for i, r in df.iterrows():
print type(r['col1']), type(r['col2']), type(r['col3'])
In particular integer, floats and strings were recognized correctly. However, I have a column that has dates in the following format: 2013-6-4. These dates were recognized as strings (not as python date-objects). Is there a way to "learn" pandas to recognized dates?
You should add parse_dates=True, or parse_dates=['column name'] when reading, thats usually enough to magically parse it. But there are always weird formats which need to be defined manually. In such a case you can also add a date parser function, which is the most flexible way possible.
Suppose you have a column 'datetime' with your string, then:
from datetime import datetime
dateparse = lambda x: datetime.strptime(x, '%Y-%m-%d %H:%M:%S')
df = pd.read_csv(infile, parse_dates=['datetime'], date_parser=dateparse)
This way you can even combine multiple columns into a single datetime column, this merges a 'date' and a 'time' column into a single 'datetime' column:
dateparse = lambda x: datetime.strptime(x, '%Y-%m-%d %H:%M:%S')
df = pd.read_csv(infile, parse_dates={'datetime': ['date', 'time']}, date_parser=dateparse)
You can find directives (i.e. the letters to be used for different formats) for strptime and strftime in this page.
Perhaps the pandas interface has changed since #Rutger answered, but in the version I'm using (0.15.2), the date_parser function receives a list of dates instead of a single value. In this case, his code should be updated like so:
from datetime import datetime
import pandas as pd
dateparse = lambda dates: [datetime.strptime(d, '%Y-%m-%d %H:%M:%S') for d in dates]
df = pd.read_csv('test.dat', parse_dates=['datetime'], date_parser=dateparse)
Since the original question asker said he wants dates and the dates are in 2013-6-4 format, the dateparse function should really be:
dateparse = lambda dates: [datetime.strptime(d, '%Y-%m-%d').date() for d in dates]
You could use pandas.to_datetime() as recommended in the documentation for pandas.read_csv():
If a column or index contains an unparseable date, the entire column
or index will be returned unaltered as an object data type. For
non-standard datetime parsing, use pd.to_datetime after pd.read_csv.
Demo:
>>> D = {'date': '2013-6-4'}
>>> df = pd.DataFrame(D, index=[0])
>>> df
date
0 2013-6-4
>>> df.dtypes
date object
dtype: object
>>> df['date'] = pd.to_datetime(df.date, format='%Y-%m-%d')
>>> df
date
0 2013-06-04
>>> df.dtypes
date datetime64[ns]
dtype: object
When merging two columns into a single datetime column, the accepted answer generates an error (pandas version 0.20.3), since the columns are sent to the date_parser function separately.
The following works:
def dateparse(d,t):
dt = d + " " + t
return pd.datetime.strptime(dt, '%d/%m/%Y %H:%M:%S')
df = pd.read_csv(infile, parse_dates={'datetime': ['date', 'time']}, date_parser=dateparse)
pandas read_csv method is great for parsing dates. Complete documentation at http://pandas.pydata.org/pandas-docs/stable/generated/pandas.io.parsers.read_csv.html
you can even have the different date parts in different columns and pass the parameter:
parse_dates : boolean, list of ints or names, list of lists, or dict
If True -> try parsing the index. If [1, 2, 3] -> try parsing columns 1, 2, 3 each as a
separate date column. If [[1, 3]] -> combine columns 1 and 3 and parse as a single date
column. {‘foo’ : [1, 3]} -> parse columns 1, 3 as date and call result ‘foo’
The default sensing of dates works great, but it seems to be biased towards north american Date formats. If you live elsewhere you might occasionally be caught by the results. As far as I can remember 1/6/2000 means 6 January in the USA as opposed to 1 Jun where I live. It is smart enough to swing them around if dates like 23/6/2000 are used. Probably safer to stay with YYYYMMDD variations of date though. Apologies to pandas developers,here but i have not tested it with local dates recently.
you can use the date_parser parameter to pass a function to convert your format.
date_parser : function
Function to use for converting a sequence of string columns to an array of datetime
instances. The default uses dateutil.parser.parser to do the conversion.
Yes - according to the pandas.read_csv documentation:
Note: A fast-path exists for iso8601-formatted dates.
So if your csv has a column named datetime and the dates looks like 2013-01-01T01:01 for example, running this will make pandas (I'm on v0.19.2) pick up the date and time automatically:
df = pd.read_csv('test.csv', parse_dates=['datetime'])
Note that you need to explicitly pass parse_dates, it doesn't work without.
Verify with:
df.dtypes
You should see the datatype of the column is datetime64[ns]
While loading csv file contain date column.We have two approach to to make pandas to
recognize date column i.e
Pandas explicit recognize the format by arg date_parser=mydateparser
Pandas implicit recognize the format by agr infer_datetime_format=True
Some of the date column data
01/01/18
01/02/18
Here we don't know the first two things It may be month or day. So in this case we have to use
Method 1:-
Explicit pass the format
mydateparser = lambda x: pd.datetime.strptime(x, "%m/%d/%y")
df = pd.read_csv(file_name, parse_dates=['date_col_name'],
date_parser=mydateparser)
Method 2:- Implicit or Automatically recognize the format
df = pd.read_csv(file_name, parse_dates=[date_col_name],infer_datetime_format=True)
In addition to what the other replies said, if you have to parse very large files with hundreds of thousands of timestamps, date_parser can prove to be a huge performance bottleneck, as it's a Python function called once per row. You can get a sizeable performance improvements by instead keeping the dates as text while parsing the CSV file and then converting the entire column into dates in one go:
# For a data column
df = pd.read_csv(infile, parse_dates={'mydatetime': ['date', 'time']})
df['mydatetime'] = pd.to_datetime(df['mydatetime'], exact=True, cache=True, format='%Y-%m-%d %H:%M:%S')
# For a DateTimeIndex
df = pd.read_csv(infile, parse_dates={'mydatetime': ['date', 'time']}, index_col='mydatetime')
df.index = pd.to_datetime(df.index, exact=True, cache=True, format='%Y-%m-%d %H:%M:%S')
# For a MultiIndex
df = pd.read_csv(infile, parse_dates={'mydatetime': ['date', 'time']}, index_col=['mydatetime', 'num'])
idx_mydatetime = df.index.get_level_values(0)
idx_num = df.index.get_level_values(1)
idx_mydatetime = pd.to_datetime(idx_mydatetime, exact=True, cache=True, format='%Y-%m-%d %H:%M:%S')
df.index = pd.MultiIndex.from_arrays([idx_mydatetime, idx_num])
For my use case on a file with 200k rows (one timestamp per row), that cut down processing time from about a minute to less than a second.
Read the existing string columns in date and time format respectively
pd.read_csv('CGMData.csv', parse_dates=['Date', 'Time'])
Resulted Columns
Concat string columns of date and time and add new column of datetype object - Remove Original columns
if want to rename the new column name then pass as dictionary as
show in below example and the new column name will be the key name,
if pass as list of column, new column name will be concate of column name passed in the list separated by _ e.g Date_Time
# parse_dates={'given_name': ['Date', 'Time']}
pd.read_csv("InsulinData.csv",low_memory=False,
parse_dates=[['Date', 'Time']])
pd.read_csv("InsulinData.csv",low_memory=False,
parse_dates={'date_time': ['Date', 'Time']})
Concat string columns of date and time and add new column of datetype object and Keep the Original columns
pd.read_csv("InsulinData.csv",low_memory=False,
parse_dates=[['Date', 'Time']], keep_date_col=True)
Want to change the format of date and time when read from csv
parser = lambda x: pd.to_datetime(x, format='%Y-%m-%d %H:%M:%S')
pd.read_csv('path', date_parser=parser, parse_dates=['date', 'time'])
If performance matters to you make sure you time:
import sys
import timeit
import pandas as pd
print('Python %s on %s' % (sys.version, sys.platform))
print('Pandas version %s' % pd.__version__)
repeat = 3
numbers = 100
def time(statement, _setup=None):
print (min(
timeit.Timer(statement, setup=_setup or setup).repeat(
repeat, numbers)))
print("Format %m/%d/%y")
setup = """import pandas as pd
import io
data = io.StringIO('''\
ProductCode,Date
''' + '''\
x1,07/29/15
x2,07/29/15
x3,07/29/15
x4,07/30/15
x5,07/29/15
x6,07/29/15
x7,07/29/15
y7,08/05/15
x8,08/05/15
z3,08/05/15
''' * 100)"""
time('pd.read_csv(data); data.seek(0)')
time('pd.read_csv(data, parse_dates=["Date"]); data.seek(0)')
time('pd.read_csv(data, parse_dates=["Date"],'
'infer_datetime_format=True); data.seek(0)')
time('pd.read_csv(data, parse_dates=["Date"],'
'date_parser=lambda x: pd.datetime.strptime(x, "%m/%d/%y")); data.seek(0)')
print("Format %Y-%m-%d %H:%M:%S")
setup = """import pandas as pd
import io
data = io.StringIO('''\
ProductCode,Date
''' + '''\
x1,2016-10-15 00:00:43
x2,2016-10-15 00:00:56
x3,2016-10-15 00:00:56
x4,2016-10-15 00:00:12
x5,2016-10-15 00:00:34
x6,2016-10-15 00:00:55
x7,2016-10-15 00:00:06
y7,2016-10-15 00:00:01
x8,2016-10-15 00:00:00
z3,2016-10-15 00:00:02
''' * 1000)"""
time('pd.read_csv(data); data.seek(0)')
time('pd.read_csv(data, parse_dates=["Date"]); data.seek(0)')
time('pd.read_csv(data, parse_dates=["Date"],'
'infer_datetime_format=True); data.seek(0)')
time('pd.read_csv(data, parse_dates=["Date"],'
'date_parser=lambda x: pd.datetime.strptime(x, "%Y-%m-%d %H:%M:%S")); data.seek(0)')
prints:
Python 3.7.1 (v3.7.1:260ec2c36a, Oct 20 2018, 03:13:28)
[Clang 6.0 (clang-600.0.57)] on darwin
Pandas version 0.23.4
Format %m/%d/%y
0.19123052499999993
8.20691274
8.143124389
1.2384357139999977
Format %Y-%m-%d %H:%M:%S
0.5238807110000039
0.9202787830000005
0.9832778819999959
12.002349824999996
So with iso8601-formatted date (%Y-%m-%d %H:%M:%S is apparently an iso8601-formatted date, I guess the T can be dropped and replaced by a space) you should not specify infer_datetime_format (which does not make a difference with more common ones either apparently) and passing your own parser in just cripples performance. On the other hand, date_parser does make a difference with not so standard day formats. Be sure to time before you optimize, as usual.
You can use the parameter date_parser with a function for converting a sequence of string columns to an array of datetime instances:
parser = lambda x: pd.to_datetime(x, format='%Y-%m-%d %H:%M:%S')
pd.read_csv('path', date_parser=parser, parse_dates=['date_col1', 'date_col2'])
Yes, this code works like breeze. Here index 0 refers to the index of the date column.
df = pd.read_csv(filepath, parse_dates=[0], infer_datetime_format = True)
No, there is no way in pandas to automatically recognize date columns.
Pandas does a poor job at type inference. It basically puts most columns as the generic object type, unless you manually work around it eg. using the abovementioned parse_dates parameter.
If you want to automatically detect columns types, you'd have to use a separate data profiling tool, eg. visions, and then cast or feed the inferred types back into your DataFrame constructor (eg. for dates and from_csv, using the parse_dates parameter).

Categories

Resources