1 回答

TA貢獻1827條經驗 獲得超9個贊
您可以通過參數提供第二個 y 編碼來將基線定義為 1 y2。使用這種方法與條形圖相對簡單:
import pandas as pd
import altair as alt
data = pd.DataFrame(
{'date': pd.date_range(start='1/1/2018', end='1/11/2018'),
'stock': [0.1, 0.3, 0.9, 1, 1.5, 1.2, 0.8, 1.1, 0.4, 0.8, 1.6],
'baseline': [1]*11})
# You could also set the bar width instead of binning
alt.Chart(data).mark_bar().encode(
x=alt.X('monthdate(date):T'),
y='stock:Q',
y2='baseline',
color = alt.condition(alt.datum.stock < 1, alt.value('grey'), alt.value('red')))
這很有效,因為條形是單獨的圖形元素,因此它們將單獨著色。面積圖是單個圖形元素,因此僅針對第一個庫存值執行條件比較,然后整個區域都以此顏色著色。為了獲得不同的顏色,我們需要將區域分成多個標記,如您鏈接的答案中所示進行分組(這也適用于條形圖)。您可以通過預先在數據框中創建分組列或通過transform_calculate.
(alt.Chart(data.reset_index()).mark_area().encode(
x=alt.X('date:T'),
y=alt.Y('stock:Q', impute={'value': 1}),
y2='baseline',
color=alt.Color('negative:N', scale=alt.Scale(range=['red', 'grey'])))
.transform_calculate(negative='datum.stock < 1'))
為什么點之間存在重疊?其原因是數據的稀疏性以及區域和線標記的默認插值方法是“線性”。如果將其更改為mark_area(interpolate='step')
,區域之間的邊界將變得清晰:
為了在保持其形狀的同時實現基線周圍區域標記的急劇過渡,數據需要具有更高分辨率。借用您鏈接的答案,您可以看到當數據稀疏時,那里的區域也會重疊:
import altair as alt
import pandas as pd
import numpy as np
x = np.linspace(2, 4, 4)
df = pd.DataFrame({'x': x, 'y': np.sin(x)})
(alt.Chart(df).mark_area().encode(
x='x',
y=alt.Y('y', impute={'value': 0}),
color='negative:N')
.transform_calculate(negative='datum.y < 0'))
如果我們將點數增加十倍 ( x = np.linspace(2, 4, 40)
),隨著插值發生在空間中更接近的點之間,過渡會變得更加尖銳(將插值從線性更改為單調,在保持形狀的同時也可能有所幫助)。
要提高時間序列數據的分辨率,您可以使用 pandasresample和interpolate方法進行上采樣。做這樣的事情時要擔心的是,您是否以有意義的方式人為地更改了數據。我發現問問自己該操作是否會改變您對數據得出的結論很有用。
(alt.Chart(data.set_index('date').resample('1h').interpolate().reset_index()).mark_area().encode(
x=alt.X('date:T'),
y=alt.Y('stock:Q', impute={'value': 1}),
y2='baseline',
color=alt.Color('negative:N', scale=alt.Scale(range=['red', 'grey'])))
.transform_calculate(negative='datum.stock < 1'))
在這里,我們上采樣到每小時的數據點,并在原始點之間進行線性插值。對我來說,這不會改變我通過研究該圖得出的結論,因為線性插值保留了區域的塊狀外觀,因此我們不會使數據看起來人為平滑。我想到的唯一缺點是,我們確實向 Altair 發送了不必要的數據量,您也許可以使用 Altair 中的轉換來執行插值,但我不知道該怎么做。
添加回答
舉報