Altair 图表 - 自定义轴格式化程序功能
Altair chart - Custom axis formatter function
我可以在 Matplotlib 中使用以下表达式:
def format_func(value, tick_number):
d = datetime.date(1998,1,1) + datetime.timedelta(value)
return d.strftime("%B")
ax.xaxis.set_major_formatter(plt.FuncFormatter(format_func))
当X-Axis值包含一年中的某一天(1-365)时,转换为对应月份的名称。
我可以在 Altair 中实现相同的功能吗?
编辑:
感谢@joelostblom。添加一段代码以指定我正在使用的确切数据框。下面代码的当前问题是,在我的示例中,我有
# pre-existing dataframe
num_days = 365 * 4 # four days
df = pd.DataFrame(
{
'Timestamp': [
(datetime.datetime.now() - datetime.timedelta(num_days) ) + datetime.timedelta(days=x)
for x in range(num_days)
],
'value': pd.Series(np.random.randn(num_days))
}
)
df = df.set_index('Timestamp')
# extra columns that may be needed by altair
df['Month'] = df.index.month_name()
df['Year'] = df.index.year
到目前为止,我已经尝试通过两种方式使用 Altair:
alt.Chart(df.reset_index()).mark_line().encode(
x='Month',
y='value',
color=alt.Color('Year:O', scale=alt.Scale(scheme='category10')),
)
或者像你建议的那样:
alt.Chart(df.reset_index()).mark_line().encode(
x=alt.X('Timestamp', axis=alt.Axis(format='%b')),
y='value',
color=alt.Color('Year:O', scale=alt.Scale(scheme='category10')),
)
你能帮我理解我做错了什么吗?
您可以使用 pandas.to_datetime
:
转换日期戳
import altair as alt
import numpy as np
import pandas as pd
# Setup data
x = np.arange(365)
source = pd.DataFrame({
'x': x,
'f(x)': np.sin(x / 50)
})
# Convert to date
source['date'] = pd.to_datetime(source['x'], unit='D', origin='2020')
alt.Chart(source).mark_line().encode(
x='date',
y='f(x)'
)
如果您想要轴上的所有月份名称,您可以更改轴格式:
alt.Chart(source).mark_line().encode(
x=alt.X('date', axis=alt.Axis(format='%b')),
y='f(x)'
)
对于您更新的示例,当有多个年份时,您可以使用 time unit aggregations in Altair/Vega-Lite。例如,使用 'monthdate(Timestamp)'
将忽略年份并按月份和日期聚合(请注意,并非 Vega-Lite 文档中的所有聚合都在 Altair 中可用)。
import pandas as pd
import altair as alt
import datetime
import numpy as np
# pre-existing dataframe
num_days = 365 * 4 # four years
df = pd.DataFrame(
{
'Timestamp': [
(datetime.datetime.now() - datetime.timedelta(num_days) ) + datetime.timedelta(days=x)
for x in range(num_days)
],
'value': pd.Series(np.random.randn(num_days))
}
)
alt.Chart(df).mark_line().encode(
x=alt.X('monthdate(Timestamp)', axis=alt.Axis(format='%b')),
y='value',
color=alt.Color('year(Timestamp):O', scale=alt.Scale(scheme='category10')),
)
我可以在 Matplotlib 中使用以下表达式:
def format_func(value, tick_number):
d = datetime.date(1998,1,1) + datetime.timedelta(value)
return d.strftime("%B")
ax.xaxis.set_major_formatter(plt.FuncFormatter(format_func))
当X-Axis值包含一年中的某一天(1-365)时,转换为对应月份的名称。
我可以在 Altair 中实现相同的功能吗?
编辑:
感谢@joelostblom。添加一段代码以指定我正在使用的确切数据框。下面代码的当前问题是,在我的示例中,我有
# pre-existing dataframe
num_days = 365 * 4 # four days
df = pd.DataFrame(
{
'Timestamp': [
(datetime.datetime.now() - datetime.timedelta(num_days) ) + datetime.timedelta(days=x)
for x in range(num_days)
],
'value': pd.Series(np.random.randn(num_days))
}
)
df = df.set_index('Timestamp')
# extra columns that may be needed by altair
df['Month'] = df.index.month_name()
df['Year'] = df.index.year
到目前为止,我已经尝试通过两种方式使用 Altair:
alt.Chart(df.reset_index()).mark_line().encode(
x='Month',
y='value',
color=alt.Color('Year:O', scale=alt.Scale(scheme='category10')),
)
或者像你建议的那样:
alt.Chart(df.reset_index()).mark_line().encode(
x=alt.X('Timestamp', axis=alt.Axis(format='%b')),
y='value',
color=alt.Color('Year:O', scale=alt.Scale(scheme='category10')),
)
你能帮我理解我做错了什么吗?
您可以使用 pandas.to_datetime
:
import altair as alt
import numpy as np
import pandas as pd
# Setup data
x = np.arange(365)
source = pd.DataFrame({
'x': x,
'f(x)': np.sin(x / 50)
})
# Convert to date
source['date'] = pd.to_datetime(source['x'], unit='D', origin='2020')
alt.Chart(source).mark_line().encode(
x='date',
y='f(x)'
)
如果您想要轴上的所有月份名称,您可以更改轴格式:
alt.Chart(source).mark_line().encode(
x=alt.X('date', axis=alt.Axis(format='%b')),
y='f(x)'
)
对于您更新的示例,当有多个年份时,您可以使用 time unit aggregations in Altair/Vega-Lite。例如,使用 'monthdate(Timestamp)'
将忽略年份并按月份和日期聚合(请注意,并非 Vega-Lite 文档中的所有聚合都在 Altair 中可用)。
import pandas as pd
import altair as alt
import datetime
import numpy as np
# pre-existing dataframe
num_days = 365 * 4 # four years
df = pd.DataFrame(
{
'Timestamp': [
(datetime.datetime.now() - datetime.timedelta(num_days) ) + datetime.timedelta(days=x)
for x in range(num_days)
],
'value': pd.Series(np.random.randn(num_days))
}
)
alt.Chart(df).mark_line().encode(
x=alt.X('monthdate(Timestamp)', axis=alt.Axis(format='%b')),
y='value',
color=alt.Color('year(Timestamp):O', scale=alt.Scale(scheme='category10')),
)