1

In a df as below:

        id      timestamp               temperature 
27581   27822   2020-01-02 07:53:05.173 19.5    
27582   27823   2020-01-02 07:53:05.273 20.0    
27647   27888   2020-01-02 10:01:46.380 20.5    
27648   27889   2020-01-02 10:01:46.480 21.0    
27649   27890   2020-01-02 10:01:48.463 21.5    
27650   27891   2020-01-02 10:01:48.563 22.0    
27711   27952   2020-01-02 10:32:19.897 21.5    
27712   27953   2020-01-02 10:32:19.997 21.0
27861   28102   2020-01-02 11:34:41.940 21.5    
...

In a for-loop that generate plot, I want to print the weekday of date inside the plot title. date is a datetime.date object. But I incurred some error when formatting the date. I tried something like this, based on this answer:

df['Date'] = df['timestamp'].dt.date     
df.set_index(df['timestamp'], inplace=True)


for date in df['Date'].unique():   
  df_date = df[df['Date'] == date]

  ...

  plt.title(date, date.strftime('%B'))    # I want to print both the date and the corresponding weekday.

The date displays date in the format 2020-01-01 which is fine, but the weekday section returned error:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-56-6cc9c07f6879> in <module>()

---> 86   plt.title(date, date.strftime('%B'))
     87 
     88   number.append(np.count_nonzero(df2['events'][minLim:maxLim]))

2 frames
/usr/local/lib/python3.6/dist-packages/matplotlib/text.py in update(self, kwargs)
    174         # Update bbox last, as it depends on font properties.
    175         sentinel = object()  # bbox can be None, so use another sentinel.
--> 176         bbox = kwargs.pop("bbox", sentinel)
    177         super().update(kwargs)
    178         if bbox is not sentinel:

AttributeError: 'str' object has no attribute 'pop'

I then tried this, based on this answer:

df['Date'] = df['timestamp'].dt.date     
df.set_index(df['timestamp'], inplace=True)


for date in df['Date'].unique():   
  df_date = df[df['Date'] == date]

  ...

  year, month, day = (int(x) for x in date.split('-'))    
  answer = datetime.date(year, month, day).weekday()
  plt.title(date, answer)

which returned

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-57-03b7529a410a> in <module>()
     82   number = []
     83   ax.autoscale() 
---> 84   year, month, day = (int(x) for x in date.split('-'))
     85   answer = datetime.date(year, month, day).weekday()
     86   plt.title(date, answer)

AttributeError: 'datetime.date' object has no attribute 'split'

Update:

I tried to create the "weekday" column in the date frame for each unique 'date' using:

for date in df['Date'].unique():   
  df_date = df[df['Date'] == date]

  df_date['Date'] = pd.to_datetime(df_date['Date'], errors='coerce')
  df_date['Weekday'] = df_date['Date'].dt.dayofweek  #Add 'Weekday' column.

  print(df_date)

which returned warnings:

/usr/local/lib/python3.6/dist-packages/ipykernel_launcher.py:7: SettingWithCopyWarning:

A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

despite the warnings dataframe df_date had been printed.But how should I make it return both date and weekday from the loop(for example "2020-04-02, Thursday")?

Should I use something like this:

weekday = df_date.loc[date, df_date['Weekday']]

to get the corresponding weekday of date in the loop?

nilsinelabore
  • 4,143
  • 17
  • 65
  • 122

1 Answers1

1

Use the weekday property of a DatetimeIndex, link. See the example at the bottom of the linked page.

Example

import pandas as pd
import matplotlib.pyplot as plt

data = [
    ["2020-01-02 10:01:48.563", "22.0"],
    ["2020-01-02 10:32:19.897", "21.5"],
    ["2020-01-02 10:32:19.997", "21.0"],
    ["2020-01-02 11:34:41.940", "21.5"],
]

df = pd.DataFrame(data)
df.columns = ["date", "temp"]

df["date"] = pd.to_datetime(df["date"])
df["weekday"] = df["date"].dt.weekday
df["day_name"] = df["date"].dt.day_name()

print(df)

for day_name in df["day_name"].unique():
    plt.figure()
    plt.plot(df["date"], df["temp"])
    plt.title(day_name)
plt.show()

which gives

                     date  temp  weekday  day_name
0 2020-01-02 10:01:48.563  22.0        3  Thursday
1 2020-01-02 10:32:19.897  21.5        3  Thursday
2 2020-01-02 10:32:19.997  21.0        3  Thursday
3 2020-01-02 11:34:41.940  21.5        3  Thursday

and the plot enter image description here


Update 04/04 in response to comment

import pandas as pd
import matplotlib.pyplot as plt

data = [
["2020-01-02 10:01:48.563", "22.0"],
["2020-01-02 10:32:19.897", "21.5"],
["2020-01-02 10:32:19.997", "21.0"],
["2020-01-02 11:34:41.940", "21.5"],
]

df = pd.DataFrame(data)
df.columns = ["timestamp", "temp"]
df["timestamp"] = pd.to_datetime(df["timestamp"])

df['Date'] = df['timestamp'].dt.date
df.set_index(df['timestamp'], inplace=True)

df['Weekday'] = df.index.day_name() 

for date in df['Date'].unique():
  df_date = df[df['Date'] == date]

  plt.figure()
  plt.plot(df_date["timestamp"], df["temp"])
  plt.title("{}, {}".format(date, df_date["Weekday"].iloc[0]))
  plt.show()

Note this will produce a plot for each unique date, I assume thats what you are after.

For the limited data example above, this produces the plot enter image description here

Hiho
  • 643
  • 4
  • 8
  • Hi Hiho, in the doc it states "This method is available on both Series with datetime values(using the dt accessor) or DatetimeIndex." but `plt.title(date, date.dayofweek())` returned `AttributeError:'datetime.date' object has no attribute 'dayofweek'`. – nilsinelabore Mar 30 '20 at 04:09
  • @nilsinelabore have added an example using (some of) your data from above. Hope that shows how to use it. – Hiho Mar 31 '20 at 07:19
  • Hi Hiho, thanks for the edit to your answer. I tried your code. I think it's working fine in the series as part of the dataframe, but I'm still struggling with inserting it into the Matplotlib title. I have created a new column with `df["weekday"] = df["Date"].dt.weekday`, and changed the title section to `plt.title(date, df['weekday'])` and it returned `TypeError: pop() takes 2 positional arguments but 3 were given`. I guess I'm not supposed to do that with the title? Any idea what should be the title arguments? If you think it's necessary, I can upload the complete code. Thanks a lot... – nilsinelabore Mar 31 '20 at 08:45
  • @nilsinelabore Its because you passing to many arguments to plt.title, it just takes a single string value (i.e. the title), so you have to get the specific weekday you want in the title. I have added a plot example of what I think you are after. – Hiho Apr 01 '20 at 16:21
  • Hi Hiho, thanks for your reply. Actually I would like to have both the date and the weekday in the title, for example '2020-04-02, Thursday'. Do you know how I can tweak my code to do that? – nilsinelabore Apr 01 '20 at 22:23
  • Please see edited question for the update. Thank you:) – nilsinelabore Apr 01 '20 at 23:37
  • @nilsinelabore You can use string formatting for this, https://pyformat.info/ seems to have a nice description of it, there are lots of other pages that explain it though (any decent python tutorial will). Have updated the answer above. – Hiho Apr 04 '20 at 03:58
  • Thank you it worked. Much appreciate your help and the resources you shared :) – nilsinelabore Apr 04 '20 at 06:51