1 回答

TA貢獻(xiàn)1827條經(jīng)驗(yàn) 獲得超9個(gè)贊
您可以通過(guò)參數(shù)提供第二個(gè) y 編碼來(lái)將基線定義為 1 y2。使用這種方法與條形圖相對(duì)簡(jiǎn)單:
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')))
這很有效,因?yàn)闂l形是單獨(dú)的圖形元素,因此它們將單獨(dú)著色。面積圖是單個(gè)圖形元素,因此僅針對(duì)第一個(gè)庫(kù)存值執(zhí)行條件比較,然后整個(gè)區(qū)域都以此顏色著色。為了獲得不同的顏色,我們需要將區(qū)域分成多個(gè)標(biāo)記,如您鏈接的答案中所示進(jìn)行分組(這也適用于條形圖)。您可以通過(guò)預(yù)先在數(shù)據(jù)框中創(chuàng)建分組列或通過(guò)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'))
為什么點(diǎn)之間存在重疊?其原因是數(shù)據(jù)的稀疏性以及區(qū)域和線標(biāo)記的默認(rèn)插值方法是“線性”。如果將其更改為mark_area(interpolate='step')
,區(qū)域之間的邊界將變得清晰:
為了在保持其形狀的同時(shí)實(shí)現(xiàn)基線周圍區(qū)域標(biāo)記的急劇過(guò)渡,數(shù)據(jù)需要具有更高分辨率。借用您鏈接的答案,您可以看到當(dāng)數(shù)據(jù)稀疏時(shí),那里的區(qū)域也會(huì)重疊:
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'))
如果我們將點(diǎn)數(shù)增加十倍 ( x = np.linspace(2, 4, 40)
),隨著插值發(fā)生在空間中更接近的點(diǎn)之間,過(guò)渡會(huì)變得更加尖銳(將插值從線性更改為單調(diào),在保持形狀的同時(shí)也可能有所幫助)。
要提高時(shí)間序列數(shù)據(jù)的分辨率,您可以使用 pandasresample和interpolate方法進(jìn)行上采樣。做這樣的事情時(shí)要擔(dān)心的是,您是否以有意義的方式人為地更改了數(shù)據(jù)。我發(fā)現(xiàn)問(wèn)問(wèn)自己該操作是否會(huì)改變您對(duì)數(shù)據(jù)得出的結(jié)論很有用。
(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'))
在這里,我們上采樣到每小時(shí)的數(shù)據(jù)點(diǎn),并在原始點(diǎn)之間進(jìn)行線性插值。對(duì)我來(lái)說(shuō),這不會(huì)改變我通過(guò)研究該圖得出的結(jié)論,因?yàn)榫€性插值保留了區(qū)域的塊狀外觀,因此我們不會(huì)使數(shù)據(jù)看起來(lái)人為平滑。我想到的唯一缺點(diǎn)是,我們確實(shí)向 Altair 發(fā)送了不必要的數(shù)據(jù)量,您也許可以使用 Altair 中的轉(zhuǎn)換來(lái)執(zhí)行插值,但我不知道該怎么做。
添加回答
舉報(bào)