前提知識:国内総生産と国民所得
食料が高くなり、交通費は変わらないのに、二つの世帯がそれぞれ生活コストが25%と10%上昇したと言っています。どちらが間違っているのでしょうか? おそらくどちらも間違っていないのです:彼らが購入するものや支出の重みが異なるからです。価格指数は多くの価格を一つの数値に合成しますが、その第一歩はバスケット(買い物かご)に何が含まれ、どのように重み付けされるかを明らかにすることです。
本稿では、二つの固定された買い物かごを用いて計算を行い、価格水準、インフレ率、実質購買力を区別します。数値は学習用の設定です。現実のCPI(消費者物価指数)における商品選択、住宅費の扱い、品質調整、重みの更新には明確な統計規則があり、この二商品例を完全な編成方法として扱うことはできません。
まず数量を固定し、次に請求額を計算する
基準期における食料は単位あたり2元、交通は1回あたり4元でした。世帯Aは毎期、食料10単位、交通5回を購入します。世帯Bは食料5単位、交通10回を購入します。ここで食料が3元に値上げされ、交通費は変わりません。
| 世帯 | 基準期の食料支出 | 基準期の交通支出 | 基準期の合計 | 原数量による新請求額 | 上昇率 |
| A | 20 | 20 | 40 | 30+20=50 | 25% |
| B | 10 | 40 | 50 | 15+40=55 | 10% |
食料自体は50%値上げしましたが、両世帯の合計請求額が50%上昇したわけではありません。支出の一部しか食料に使われていないからです。Aの基準期の食料の重みは50%、Bは20%です。この固定かごの例では、総上昇率はそれぞれ 50%×50%=25% と 20%×50%=10% となります。
固定かご価格指数は通常、「当期に基準期の数量を購入するコスト / 基準期に同じ数量を購入するコスト ×100」として表されます。Aの場合、100から125へ、Bの場合100から110へ変動します。指数の125は125元を意味するのではなく、基準期の100に対する相対的な水準を示しています。
図を準備しています
条件を変えて結果を確かめる基期100。食料比率50%、値上げ50%、交通不変なら指数125。比率と値上げを別々に変更できる。
{"id":"economics-18","title":"条件を変えて結果を確かめる","summary":"基期100。食料比率50%、値上げ50%、交通不変なら指数125。比率と値上げを別々に変更できる。","height":750,"html":"<div class=\"controls\"><label for=\"weight\"><span data-i18n=\"weight\"></span><output id=\"out-weight\" for=\"weight\"></output><input id=\"weight\" type=\"range\" min=\"0\" max=\"100\" step=\"5\" value=\"50\"></label><label for=\"rise\"><span data-i18n=\"rise\"></span><output id=\"out-rise\" for=\"rise\"></output><input id=\"rise\" type=\"range\" min=\"0\" max=\"100\" step=\"5\" value=\"50\"></label></div><button id=\"reset\" type=\"button\" data-i18n=\"reset\"></button><div id=\"graphic\"></div><div id=\"results\" class=\"results\" role=\"status\" aria-live=\"polite\" data-i18n-label=\"result\"></div><p class=\"scope\" data-i18n=\"scope\"></p>","css":"body{padding:20px}h2{font-size:19px;margin:0 0 14px}.controls{display:grid;gap:16px}label{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px;font-size:15px}select,input{grid-column:1/-1;width:100%;min-width:0;font:inherit}select{padding:10px;background:var(--paper);color:var(--ink);border:1px solid var(--rule);border-radius:6px;white-space:normal}input{accent-color:var(--accent)}button{min-height:44px;margin:16px 0;font:inherit}.plot{display:block;width:100%;max-width:560px;height:auto;margin:auto}.plot text{fill:var(--ink);font-size:14px}.legend{display:flex;gap:12px;flex-wrap:wrap;margin:8px 0;font-size:14px}.legend i{display:inline-block;width:16px;height:3px;margin-right:5px;vertical-align:middle}.results{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;margin-top:16px}.metric{border:1px solid var(--rule);padding:10px;border-radius:6px;min-width:0}.metric span{display:block;font-size:14px;min-height:3.5em;overflow-wrap:anywhere}.metric strong{font-size:22px;font-weight:600}.barrow{margin:14px 0;font-size:15px}.barlabel{display:flex;justify-content:space-between;gap:10px}.bar{height:16px;background:var(--surface);margin-top:5px}.bar i{display:block;height:100%;background:var(--accent)}.stack{display:flex;height:35px;margin:15px 0}.stack span{display:flex;align-items:center;justify-content:center;color:var(--paper);font-size:13px}.scope{font-size:14px;color:var(--muted);margin:14px 0 0;line-height:1.65}@media(max-width:380px){body{padding:14px 10px}.results{gap:6px}.metric{padding:8px}.metric strong{font-size:19px}}.accounts{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}.account{border:1px solid var(--rule);border-radius:8px;padding:12px;min-width:0}.account h3{font-size:16px;margin:0 0 12px}.account dl{margin:0}.account dt{font-size:13px;overflow-wrap:anywhere}.account dd{margin:2px 0 12px;font-variant-numeric:tabular-nums}.account .changed{font-weight:700;color:var(--accent)}.area-legend{font-size:14px;line-height:1.7}.area-legend span{display:block}.area-legend i{display:inline-block;width:12px;height:12px;margin-right:6px}@media(max-width:480px){.accounts{grid-template-columns:1fr}}","js":"const N=18,DEFAULTS={\"weight\": 50, \"rise\": 50};\n/* Pure, deterministic teaching models. Values are synthetic, not estimates. */\nfunction economy(n,p){\n if(n===6){const q=p.remaining,P0=10,P1=12,Q0=100;return{metrics:{oldRevenue:P0*Q0,newRevenue:P1*q,retainedGain:(P1-P0)*q,lostRevenue:P0*(Q0-q),elasticity:Math.abs(((q-Q0)/((q+Q0)/2))/((P1-P0)/((P1+P0)/2)))},revenueAreas:{remaining:q,oldPrice:P0,newPrice:P1,oldQuantity:Q0}};}\n if(n===5){const shift=p.scenario===1?20:0,supply=p.scenario===2?-20:0,P=(100+shift-supply)/20,Q=20+supply+10*P;return{metrics:{price:P,quantity:Q},plot:{xmax:140,ymax:14,x:'quantity',y:'price',lines:[{key:'demand',points:[[0,(120+shift)/10],[120+shift,0]]},{key:'supply',points:[[Math.max(0,20+supply),0],[140,(120-supply)/10]]},{key:'base',points:[[0,5],[140,5]],dash:true}],dot:[Q,P]}};}\n if(n===8){const b=p.response,bs=10,t=p.tax,Pb=5+bs*t/(b+bs),Ps=5-b*t/(b+bs),Q=70-b*bs*t/(b+bs);return{metrics:{buyer:Pb,seller:Ps,quantity:Q,revenue:t*Q,loss:.5*t*(70-Q)},plot:{xmax:100,ymax:20,x:'quantity',y:'price',areas:[{key:'revenue',points:[[0,Ps],[Q,Ps],[Q,Pb],[0,Pb]]},{key:'loss',points:[[Q,Ps],[Q,Pb],[70,5]]}],lines:[{key:'demand',points:[[0,5+70/b],[Math.min(100,70+5*b),Math.max(0,5+(70-100)/b)]]},{key:'supply',points:[[20,0],[100,8]]},{key:'base',points:[[0,5],[100,5]],dash:true},{key:'wedge',points:[[Q,Ps],[Q,Pb]]}],dot:[Q,Pb]}};}\n if(n===18){let index=100+p.weight*p.rise/100;return{metrics:{index,inflation:index-100},bars:[{key:'base',v:100},{key:'new',v:index}],max:180};}\n if(n===19){let E=60,U=10,N=30;if(p.scenario===1){E+=5;U-=5;}if(p.scenario===2){U-=5;N+=5;}if(p.scenario===3){U+=5;N-=5;}return{metrics:{employment:E,unemployment:U,participation:100*(E+U)/100,urate:100*U/(E+U),erate:E},stack:[E,U,N],stackKeys:['employment','unemployment','outside']};}\n if(n===20){const step=p.scenario;let reserves=100,loan=0,deposit=80,equity=20,br=0,bd=0;if(step!==0){loan=60;deposit=140;}if(step===2){reserves-=60;deposit-=60;br=60;bd=60;}if(step===3){loan=40;deposit=120;}const vals={reserves,loan,deposit,equity,bankBreserves:br,bankBdeposits:bd,borrowerDeposit:step===2?0:loan,borrowerGoods:step===2?60:0,borrowerDebt:loan,merchantDeposit:bd,merchantGoods:step===2?0:60};const prev=step>1?economy(20,{scenario:1}).accounts:economy20initial();return{metrics:{reserves,loan,deposit,equity,bankBreserves:br,bankBdeposits:bd,assets:reserves+loan,liabilities:deposit+equity},accounts:vals,ledger:[['bankA',['reserves','loan','deposit','equity']],['bankB',['bankBreserves','bankBdeposits']],['borrower',['borrowerDeposit','borrowerGoods','borrowerDebt']],['merchant',['merchantDeposit','merchantGoods']]].map(([title,keys])=>({title,items:keys.map(key=>({key,value:vals[key],delta:vals[key]-prev[key]}))}))};}\n if(n===22){const c=p.consume,shock=p.shock,rounds=Array.from({length:8},(_,k)=>shock*c**k);return{metrics:{total:shock/(1-c),shown:rounds.reduce((a,b)=>a+b,0),multiplier:1/(1-c)},bars:rounds.map((v,k)=>({label:String(k+1),v})),max:100,rounds};}\n if(n===25){const e=p.rate;return{metrics:{importBill:10*e,exportBill:70/e,debtBill:100*e},bills:true};}\n if(n===26){const A=p.tech,s=p.save/100,d=.1,k=(s*A/d)**2,y=A*Math.sqrt(k),trajectory=[];let current=25;for(let t=0;t<=60;t++){const output=A*Math.sqrt(current),investment=s*output,depreciation=d*current;trajectory.push({t,k:current,y:output,consumption:(1-s)*output,investment,depreciation});current+=investment-depreciation;}return{metrics:{capital:k,output:y,consumption:(1-s)*y},trajectory,plot:{xmax:60,ymax:Math.max(10,...trajectory.map(a=>a.y))*1.1,x:'period',y:'perPersonFlow',lines:[{key:'baselineConsumption',points:[[0,7.5],[60,7.5]],dash:true},{key:'outputPath',points:trajectory.map(a=>[a.t,a.y])},{key:'consumptionPath',points:trajectory.map(a=>[a.t,a.consumption])}]}};}\n throw Error('Unknown lesson');\n}\nfunction economy20initial(){return{reserves:100,loan:0,deposit:80,equity:20,bankBreserves:0,bankBdeposits:0,borrowerDeposit:0,borrowerGoods:0,borrowerDebt:0,merchantDeposit:0,merchantGoods:60};}\nif(typeof module!=='undefined')module.exports={economy};\n\nfunction renderTeachingView(r,el){\n if(r.ledger){\n el.innerHTML='<div class=\"accounts\">'+r.ledger.map(a=>'<section class=\"account\"><h3>'+escape(viz.t(a.title))+'</h3><dl>'+a.items.map(v=>`<dt>${escape(viz.t(v.key))}</dt><dd class=\"${v.delta?'changed':''}\">${viz.number(v.value)} (${v.delta>0?'+':''}${viz.number(v.delta)})</dd>`).join('')+'</dl></section>').join('')+'</div><p class=\"scope\">'+escape(viz.t('delta'))+'</p>';\n $('#results').hidden=true;\n }\n if(r.revenueAreas){const a=r.revenueAreas,x=q=>45+q*2.65,y=p=>213-p*14,q=a.remaining;\n let s=`<svg class=\"plot\" viewBox=\"0 0 360 270\" role=\"img\" aria-label=\"${escape(viz.t('figure'))}\"><path d=\"M45 28V213H322\" fill=\"none\" stroke=\"var(--rule)\"/>`;\n const rect=(x0,x1,p0,p1,c)=>`<rect x=\"${x(x0)}\" y=\"${y(p1)}\" width=\"${(x1-x0)*2.65}\" height=\"${(p1-p0)*14}\" fill=\"${c}\" fill-opacity=\".48\" stroke=\"${c}\"/>`;\n s+=rect(0,q,0,10,'#5277ab')+rect(0,q,10,12,'#247756')+rect(q,100,0,10,'#b56838');\n for(const p of[0,10,12])s+=`<text x=\"37\" y=\"${y(p)+4}\" text-anchor=\"end\">${p}</text>`;\n for(const v of[0,50,100])s+=`<text x=\"${x(v)}\" y=\"235\" text-anchor=\"middle\">${v}</text>`;\n s+=`<text x=\"45\" y=\"20\">${escape(viz.t('price'))}</text><text x=\"310\" y=\"261\" text-anchor=\"end\">${escape(viz.t('quantity'))}</text></svg>`;\n el.innerHTML=s+'<div class=\"area-legend\">'+[['retainedBase','#5277ab'],['retainedGain','#247756'],['lostRevenue','#b56838']].map(([k,c])=>`<span><i style=\"background:${c}\"></i>${escape(viz.t(k))}</span>`).join('')+'</div>';\n }\n}\n\nconst $=s=>document.querySelector(s),col=['var(--accent)','var(--second)','#7581ae','#b36b47'];\nconst escape=s=>String(s).replace(/[&<>\"']/g,c=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));\nfunction render(){\n let p={};for(const k of Object.keys(DEFAULTS)){p[k]=Number($('#'+k).value);let o=$('#out-'+k);if(o)o.textContent=viz.number(p[k]);}\n const r=economy(N,p);document.body.dataset.result=JSON.stringify(r.metrics);document.body.dataset.params=JSON.stringify(p);\n $('#results').innerHTML=Object.entries(r.metrics).map(([k,v])=>`<div class=\"metric\"><span>${escape(viz.t(k))}</span><strong data-metric=\"${k}\">${viz.number(v,2)}</strong></div>`).join('');\n const el=$('#graphic');el.replaceChildren();\n if(r.plot){const a=r.plot,x=q=>48+q/a.xmax*278,y=v=>205-v/a.ymax*164;\n let svg=`<svg class=\"plot\" viewBox=\"0 0 360 258\" role=\"img\" aria-label=\"${escape(viz.t('figure'))}\"><path d=\"M48 30V205H333\" fill=\"none\" stroke=\"var(--rule)\"/>`;\n for(const q of [0,a.xmax/2,a.xmax])svg+=`<text x=\"${x(q)}\" y=\"226\" text-anchor=\"middle\">${viz.number(q,1)}</text>`;\n for(const v of [0,a.ymax/2,a.ymax])svg+=`<text x=\"39\" y=\"${y(v)+4}\" text-anchor=\"end\">${viz.number(v,1)}</text>`;\n svg+=`<text x=\"48\" y=\"20\">${escape(viz.t(a.y))}</text><text x=\"326\" y=\"251\" text-anchor=\"end\">${escape(viz.t(a.x))}</text>`;\n (a.areas||[]).forEach((region,j)=>{svg+=`<polygon points=\"${region.points.map(([xx,yy])=>x(xx)+','+y(yy)).join(' ')}\" fill=\"${j===0?'#4c8c9d':'#bd7446'}\" fill-opacity=\".30\"/>`;});\n a.lines.forEach((l,j)=>{svg+=`<polyline fill=\"none\" stroke=\"${col[j]}\" stroke-width=\"${l.key==='wedge'?5:2.5}\" ${l.dash?'stroke-dasharray=\"5 4\"':''} points=\"${l.points.map(([xx,yy])=>x(xx)+','+y(yy)).join(' ')}\"/>`;});\n if(a.dot)svg+=`<circle cx=\"${x(a.dot[0])}\" cy=\"${y(a.dot[1])}\" r=\"5\" fill=\"var(--ink)\"/>`;\n el.innerHTML=svg+'</svg><div class=\"legend\">'+a.lines.map((l,j)=>`<span><i style=\"background:${col[j]}\"></i>${escape(viz.t(l.key))}</span>`).join('')+(a.areas||[]).map((a,j)=>`<span><i style=\"height:10px;background:${j===0?'#4c8c9d':'#bd7446'}\"></i>${escape(viz.t(a.key))}</span>`).join('')+'</div>';\n }else if(r.bars){el.innerHTML=r.bars.map(b=>`<div class=\"barrow\"><div class=\"barlabel\"><span>${escape(b.key?viz.t(b.key):viz.t('round')+' '+b.label)}</span><strong>${viz.number(b.v)}</strong></div><div class=\"bar\"><i style=\"width:${Math.abs(b.v)/Math.max(r.max,...r.bars.map(a=>Math.abs(a.v)))*100}%\"></i></div></div>`).join('')+(N===22?`<p class=\"scope\">${escape(viz.t('negative'))}</p>`:'');\n }else if(r.stack){el.innerHTML='<div class=\"stack\">'+r.stack.map((v,j)=>`<span style=\"width:${v}%;background:${col[j]}\">${v}</span>`).join('')+'</div><div class=\"legend\">'+r.stackKeys.map((k,j)=>`<span><i style=\"background:${col[j]}\"></i>${escape(viz.t(k))}</span>`).join('')+'</div>';}\nrenderTeachingView(r,el);\n}\nfor(const k of Object.keys(DEFAULTS))$('#'+k).addEventListener('input',render);\n$('#reset').addEventListener('click',()=>{for(const[k,v]of Object.entries(DEFAULTS))$('#'+k).value=v;render();});render();\n","audio":false,"strings":{"base":"基準","figure":"現在の条件による図。正確な値は下の結果に示す。","index":"物価指数","inflation":"バスケット上昇率 / %","new":"変更後","reset":"基準に戻す","result":"計算結果","rise":"食料価格の上昇率 / %","scope":"基期100。食料比率50%、値上げ50%、交通不変なら指数125。比率と値上げを別々に変更できる。","weight":"食料の基期支出比率 / %"}}
まず食料の上昇率を50%のまま保ち、基準期の食料の重みだけを変更します。この結果は、同じ価格変化がどのように異なる生活体験に対応するかを示しており、あなたの重みの変化によって食品価格自体が変わるわけではありません。次に重みを固定して上昇率を変え、「価格が変わったこと」と「合成方法が変わったこと」を明確に区別します。
インフレが鈍化しても、物が安くなったわけではない
Aの価格指数が100から125へ変動したとき、第一期のインフレ率は25%です。次の期に125から127.5へ変動した場合、インフレ率は (127.5−125)/125=2% となります。インフレ率は大幅に鈍化しましたが、価格水準は前期比で2%高く、初期比では27.5%高くなっています。
| 時期 | 価格指数 | 前期比上昇率 |
| 基準期 | 100 | — |
| 第一期 | 125 | 25% |
| 第二期 | 127.5 | 2% |
値上げのペースが遅くなることを、インフレの鈍化と呼びます。価格水準が下落してこそ、デフレです。125から122.5へ下がってこそ、−2%となります。「インフレが2%に低下した」ことを「価格が2%下落した」と解釈すると、変化の速度と水準が混同されます。
前年同月比と前月比を比較する際には、ベース(基数)も考慮する必要があります。ある月の価格が不変でも、1年前に異常な値上げがあった場合、前年同月比の上昇率は低下する可能性があります。これだけで、現在の需要や生産能力に同程度の変化があったことを意味するわけではありません。
賃金が上昇したのに、なぜ購買力が低下するのか
世帯Aの名目可処分所得は40から44へ、10%上昇しました。一方、同じかごの価格は40から50へ、25%上昇しました。以前はかご1個分が購入できましたが、今は 44/50=0.88 個分しか購入できず、購買力は12%低下しました。
実質変化の正確な関係は (1+名目成長率)/(1+物価上昇率)−1 で、ここでは 1.10/1.25−1=−12% となります。単に 10%−25%=−15% と引くのは差分に過ぎず、上昇率が大きい場合には正確な実質成長率として扱うことはできません。変化が小さい場合にのみ、引き算は一般的な近似として使えます。
同様に、預金金利が5%で関連物価が2%上昇した場合、1年後の実質購買力の変化は 1.05/1.02−1≈2.94% となります。税制や使用される価格指数も考慮する必要がありますが、名目と実質を明確に区別しておかないと、口座残高の増加を自動的に等しい豊かさの増加と解釈してしまいます。
代替行動と品質変化を戻す
食料が高騰した後、Aは特定の食品を減らし、代替品を購入する可能性があります。かごが固定でなくなれば、実際の請求額は25%上昇しないかもしれません。しかし、請求額が上がらないからといって、それが購入量の減少や品質の低下によるものではなく、生活コストが変わらなかったとすぐに言うことはできません。
逆に、新商品の品質が向上した場合、表示価格の上昇がすべて「同じものが高くなった」ことを意味するわけではありません。現実の統計では、仕様の変更、品質差、季節変動、重みの更新などが処理され、各手法には独自の適用範囲があります。固定かご指数、他の加重指数、理想的な生活コスト概念は、説明なしに交換して使うことはできません。
CPIは通常、住民の消費価格に焦点を当てており、すべての資産価格や国内の全生産物の価格を意味するものではありません。GDPデフレーターなどの価格指標は、別の対象グループをカバーしています。コアインフレは、特定の指標に基づいて変動の大きい項目を除外し、トレンドを観察するために用いられ、これらの項目が家庭にとって重要でないことを示すものではありません。
価格がどのように測定されるか、そしてなぜ上昇するかは別の問題
同じ指数の上昇でも、需要の増大、エネルギー供給の阻害、為替レートの変動、コストの転嫁、あるいは複数の要因に起因する可能性があります。指数は単に価格の結果を記述するだけで、それがどの要因によるものかを自動的に教えてくれるわけではありません。
もし主要因が輸入エネルギーの値上げであれば、企業のコスト増が価格を押し上げ、産出量を圧迫する可能性があります。もし需要が既存の生産能力を広く超えている場合、価格と産出量の短期的な変化は異なる可能性があります。これを区別するには、インフレを見るだけでなく、部門別価格、数量、賃金、生産能力、受注、期待などを組み合わせる必要があり、インフレが見られたからといって唯一の原因を当てはめることはできません。
期待は現在の賃金、見積もり、融資条件にも影響を与えます。長期的に安定した価格期待は、一時ショックの伝播を変化させることができますが、「期待」という言葉は、調査、契約、市場などの証拠に基づくべきであり、説明できない場合の万能な言葉として使ってはいけません。財政・金融政策の章では、需要と融資の経路をそれぞれ追跡します。
新しいかごで検証する
ある世帯の基準期における食料支出の割合は30%で、食料が20%値上げし、他の商品は不変、数量は固定されています。指数は100からどのようになりますか? 収入が5%上昇した場合、実質購買力はどのように変化しますか?
推論を展開
かご全体の上昇率は 30%×20%=6% であり、指数は106になります。実質購買力の変化は 1.05/1.06−1≈−0.94% です。食料の上昇率20%を全体のかごの上昇率として代用することはできず、名目収入が上昇したからといって、実質的な改善があるとは断言できません。
報道でインフレ率が8%から3%に低下したと伝えられ、ある読者が「スーパーの価格は去年よりまだ高いので、統計は間違っている」と反論しています。これらは同時に成立し得ますか?
推論を展開
成立します。3%でも物価は全体的に上昇しており、単に上昇ペースが遅くなっただけです。スーパーの商品は、全体のかごとは異なる重みや変動を持っている可能性があります。時期(前年同月比か前月比か)、部門別指数と全体指数、そして矛盾がないかどうかをまず確認する必要があります。個人の請求額と統計指数は異なるものであり、自動的にどちらかが間違っていることを意味するわけではありません。
参考資料
以下は概念・統計定義の参考資料です。数値例と図は独自の教材用設定です。
BLS · Consumer Price Index FAQ · BEA · Gross Domestic Product