Public
Edited
Dec 1, 2022
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
camscanner1111202200119_3 = FileAttachment("CamScanner 11-11-2022 00@1.19_3.jpg").image()
Insert cell
Insert cell
camscanner111120220019 = FileAttachment("CamScanner 11-11-2022 00.19.jpg").image()
Insert cell
Insert cell
camscanner111120220019_2 = FileAttachment("CamScanner 11-11-2022 00.19_2.jpg").image()
Insert cell
Insert cell
Insert cell
Insert cell
articlesWithUsaPolicyCitations
Insert cell
Insert cell
articlesWithUsaPolicyCitations.map((d,i)=>d["Article publication date"]=new Date (d["Article publication date"]))
Insert cell
articlesWithUsaPolicyCitations.map((d,i)=>d["Policy citation date"]=(new Date (d["Policy citation date"])))
Insert cell
articlesWithUsaPolicyCitations.sort((a,b)=>a["Article publication date"]-(b["Article publication date"]) || a["Policy citation date"]-(b["Policy citation date"]))
Insert cell
// filtering articles that are not published and cited within the timeline: 2010 to 2021
filteredArticles=articlesWithUsaPolicyCitations.filter(d=>{var t= d3.timeFormat("%Y")(d["Policy citation date"]); var t1= d3.timeFormat("%Y")(d["Article publication date"]); return (t>=2010 & t<2022 & t1>=2010 & t1<2022 & t>=t1 )})
Insert cell
//filteredArticles
Insert cell
//articlesWithUsaPolicyCitations
Insert cell
article=d3.group(filteredArticles, d=> d3.timeFormat("%Y")(d["Article publication date"]), d=> d3.timeFormat("%Y")(d["Policy citation date"]))
Insert cell
articles=d3.group(filteredArticles, d=> d3.timeFormat("%Y")(d["Article publication date"]),d => d.Title)
Insert cell
articles1=d3.group(filteredArticles, d=> d3.timeFormat("%Y")(d["Article publication date"]))
Insert cell

article1=d3.group(filteredArticles, d=> (d["Title"]))
Insert cell
//setting citation serial of the policy document(s) for each research article
[...article1.keys()].map((v)=>article1.get(v).map((v1,k)=>v1.citationSerial=(k+1)))
Insert cell
//[...article1.keys()].map((v)=>article1.get(v).forEach(v1=>arr.push(v1.values)))
Insert cell
filteredarticles2=[].concat(...[...article1.values()])
Insert cell
//filteredarticles2//[...article1.keys()].map((v)=>article1.get(v).map((v1,k)=>k))
Insert cell
//yarn add multikey-map
Insert cell
//import MultikeyMap from 'multikey-map';
Insert cell
//v.get(ke)
Insert cell
// calculating and assigning citation lag of each policy citation
filteredArticles.map(d=>d.citationLag=Math.ceil((d["Policy citation date"].getTime()-d["Article publication date"].getTime()) /(1000*3600*24)))
Insert cell
filteredArticles
Insert cell
//articles1.get("2010")
//q=p.map(d=>[...articles.get(d).values()])
Insert cell
//reduce((accumulator, currentValue) => { /* … */ })
//q.map(d1=>d1.map(d2=>d2.forEach(d4=>d4.Title)))

Insert cell
//articles1.get("2010").length//.length
Insert cell
//[...article.keys()].map(d=>[...article.get(d).keys()].map((d1)=>article.get(d).get(d1).length))
Insert cell
//[...article.keys()].map(d=>{var initial=0; [...article.get(d).keys()].map((d1)=>{initial=initial+article.get(d).get(d1).length}); return initial})
Insert cell
//article.get("2011").keys()//.get( "2016").length
Insert cell
tableData = [];
Insert cell
[...article.keys()].forEach(d=>
[...article.get(d).keys()].forEach(d1=>
{
var obj = {
"publicationYear": d,
"publicationCount":articles.get(d).size,
"totalCitingPolicyCount":articles1.get(d).length,
"citationYear":d1 ,
"citingPolicyCount":article.get(d).get(d1).length};
tableData.push(obj)
} ))
Insert cell
tableData
Insert cell
pub_dates=new Set()
Insert cell
cite_dates=new Set()
Insert cell
filteredArticles.filter(d=> pub_dates.add(d3.timeFormat("%Y")(d["Article publication date"])))
Insert cell
//filteredArticles.map(d=> cite_dates.add(d3.timeFormat("%Y")(d["Policy citation date"])))
Insert cell
filteredArticles.map(d=> cite_dates.add(d3.timeFormat("%Y")(d["Policy citation date"])))
Insert cell
pub_dates
Insert cell
pub_years=Array.from(pub_dates).sort((a,b)=>{return a-b})
Insert cell
cite_dates
Insert cell
cite_years=Array.from(cite_dates).sort((a,b)=>{return a-b})
Insert cell
Insert cell
Plot.plot({
width: 600,
height: 700,
marginTop: 40,
marginBottom: 80,
marginLeft: 60, // space to the left of the chart
color: {legend: true},
style: {fontSize:12},
x: {
type: "band",
tickRotate: -90 // rotates x-axis tick labels (dates)
//tickFormat: "%b %Y" // display dates in 'Mon Year" format
},
// y:{type: "log"},
marks: [Plot.ruleY([0]),Plot.dot(tableData, {
x:"publicationYear",
y: "citingPolicyCount",
fill: "citationYear",
r:"citingPolicyCount",
sort:"citationYear"}), Plot.line(tableData, {
x:"publicationYear",
y: "citingPolicyCount",
//z: "citationYear",
// r:"citingPolicyCount",
sort:"citationYear"
})]//reverse: false
})
Insert cell
{
const plot = Plot.plot({
width: 500,
height: 500,
padding:0,
color: {legend: true},
style: {fontSize:12},
x: {axis: "top"},
//y: {axis: null},
// color: {
// type: "categorical",
// scheme: d3.schemeSet3
// },
marks: [
Plot.cell(tableData, {
x: "publicationYear",
y: "citationYear",
rx: 5, ry: 10,
fill: "citingPolicyCount",
inset: 15
// title: d => `${chartData[d.index].territory}\n${d3.format(",d")(chartData[d.index].profit)} (${chartData[d.index].ratio.toFixed(1)}%)`
})
]
})
// return wrap(
// Swatches({color: d3.scaleOrdinal(chartData.map(d => d.territory), d3.schemeTableau10)}),
// plot
// )
return plot;
}
Insert cell
Plot.plot({
width: 600,
height: 400,
marginTop: 40,
marginBottom: 80,
marginLeft: 60,
inset: 15,
grid: false,
color: {
legend: true,
},
marks: [
Plot.ruleY([0]),
Plot.dot(tableData, {x: "publicationYear", y: "citingPolicyCount",r: "citingPolicyCount",stroke: "citationYear", fill: "citationYear" ,
sort:"citationYear"}),
Plot.line(tableData, {x: "publicationYear", y: "citingPolicyCount",stroke: "citationYear" ,
sort:"citationYear"})
]
})
Insert cell
Plot.plot({
width: 600,
height: 300,
marginTop: 40,
marginBottom: 60,
marginLeft: 60,
color: {legend: true},
x: { grid: true },
y: { grid: true, nice: true,label: "↑ Count" },
marks: [
// Plot.dot(tableData, { x: "publicationYear", y: "publicationCount", stroke: "publicationCount",marker: "circle" }),
// Plot.dot(tableData, { x: "publicationYear", y: "totalCitingPolicyCount", stroke: "totalCitingPolicyCount", marker: "circle" })
Plot.areaY(tableData, { x: "publicationYear", y: "publicationCount", z:"publicationCount" }),
Plot.areaY(tableData, { x: "publicationYear", y: "totalCitingPolicyCount"})
]
})
Insert cell
filteredArticles
Insert cell
Plot.plot({
width: 900,
height: 600,
marginTop: 40,
marginBottom: 80,
marginLeft: 60,
inset: 8,
grid: false,
color: {
legend: true,
},
marks: [
Plot.ruleY([0]),
Plot.dot(filteredArticles, {x: "Article publication date", y: "citaionLag",stroke: "citaionSerial" ,
sort:"Article publication date"})
]
})


Insert cell
{
"data": {"url": "data/stocks.csv"},
"mark": "line",
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "price", "type": "quantitative"},
"color": {"field": "symbol", "type": "nominal"}
}
}
Insert cell
Plot.plot({
width: 900,
height: 600,
marginTop: 40,
marginBottom: 80,
marginLeft: 60,
inset: 8,
grid: false,
color: {
legend: true,
},
marks: [
Plot.ruleY([0]),
Plot.dot(filteredArticles, {x: "Article publication date", y: "citaionLag",stroke: "citaionLag" ,
sort:"Article publication date"})
]
})
Insert cell

Plot.plot({
width: 800,
height: 700,
marginTop: 40,
marginBottom: 30,
marginLeft: 60,
color: {legend: true},
style: "overflow: visible;",
x: {
//type: "band",
grid: true,
label: "↑ citaionLag",
tickFormat: formatChange
},
marks: [
Plot.ruleX([0]),
Plot.areaX(filteredarticles2, {
y: "citationSerial",
x: "citaionLag",
stroke: "citaionLag",
marker: "circle"
})
]
})

Insert cell
Plot.plot({
height: 500,
marginLeft: 80,
x: {
line: true
},
y: {
line: true
},
color: {
legend: true
},

marks: [
Plot.dot(filteredarticles2, {
x: "USA citation count",
y: "Article publication date",
r: "Cited by type",
fill: "region",
fillOpacity: 0.4,
stroke: "black"
}),
Plot.tickX(
filteredarticles2,
Plot.groupY(
{ x: "median" },
{
x: "USA citation count",
y: "Article publication date",
stroke: "Cited by type",
strokeWidth: 4,
strokeOpacity: 0.4
}
)
),
Plot.text(
filteredarticles2,
Plot.groupY(
{ x: "median", text: "median" },
{
x: "Article publication date",
y: "USA citation count",
text: "Cited by type",
fontSize: 20,
dx: 15,
dy: -30
}
)
)
]
})
Insert cell
Plot.plot({
width: 800,
height: 700,
marginTop: 40,
marginBottom: 60,
marginLeft: 60,
color: {legend: true},
style: "overflow: visible;",
y: {
type: "log",
grid: true,
label: "↑ citingPolicyCount",
tickFormat: formatChange
},
marks: [
Plot.ruleY([1]),
Plot.line(tableData, Plot.normalizeY({
x: "publicationYear",
y: "citingPolicyCount",
stroke: "citationYear",
marker: "circle"
})),
Plot.text(tableData, Plot.selectLast(Plot.normalizeY({
x: "publicationYear",
y: "citingPolicyCount",
z: "citationYear",
text: "citationYear",
textAnchor: "start",
dx: 3
})))
]
})
Insert cell
formatChange = {
const format = d3.format("+d");
return x => format((x - 1) * 100);
}
Insert cell
Plot.plot({
width: 600,
height: 500,
marginTop: 40,
marginBottom: 60,
marginLeft: 60,
color: {legend: true},
y: {
grid:true,
inset: 8
//tickRotate:-90
},
x:{type: "log"},
marks: [
Plot.boxX(tableData, {y: "publicationYear", x: "citingPolicyCount", z:"citationYear", stroke: "citationYear",
sort:"citationYear"})
]
})
Insert cell
vl.markRect()
.data(tableData)
.encode(
vl.x().fieldN("publicationYear"),
vl.y().fieldO("citationYear"),
vl.color().fieldQ("citingPolicyCount"),
//vl.color().average("citingPolicyCount"),
vl.tooltip().fieldQ("citingPolicyCount"),
)
.render()
Insert cell
vegalite = require("@observablehq/vega-lite@0.0")
Insert cell
import {vl} from '@vega/vega-lite-api-v5'
Insert cell
filteredarticles2
Insert cell
vegalite({
data: {values: filteredArticles},
"width": 700,
"height": 300,
"mark": "bar",
"config": {
"axis": {
"titleFontSize": 16
},
"legend": {
}
},
// adds new column to define order - maybe there is a better way?. Change order here to change order of bars
// some other sorting options, if you want to sort by metric (count, median, etc): // https://vega.github.io/vega-lite/docs/sort.html
// "transform": [{
// "calculate": "if(datum.citationSerial === 1, 0, if(datum.citationSerial === 2, 1, 2))",
// "as": "citationOrder"
// }],
"encoding": {
"x": {
"bin": {"maxbins":20},
"field": "citationLag",
"axis": {
"title": "lag (binned)"
},
"type": "quantitative",
},
"y": {
"aggregate": "count",
"type": "quantitative"
}
// // order bars based on newly created OriginOrder field
// "order": {
// "field": "citationSerial",
// "type": "quantitative",
// },
// "color": {
// "field": "citationSerial",
// "type": "quantitative",
// // "scale": {
// // "domain": ["USA","Japan","Europe"],
// // "range": ["#aaa", "steelblue", "#ccc"]
// // },
// "legend": {"title": "cite serial"}
// }
}
})
Insert cell
vl.markBar()
.data(filteredArticles)
.title("Histogram of Daily Max Temperatures in Seattle (2012-2015)")
.encode(
vl.x().fieldQ('citationLag').bin(true),
vl.y().aggregate("count")
)
.render()
Insert cell
filteredarticles2
Insert cell
function treeMap(){
const root = d3.hierarchy(article).count()
.sort((a, b) => b.height - a.height || b.value - a.value);
const treemap = d3.treemap()
.tile(d3.treemapSquarify) // treemapBinary
.size([700, 450])
.padding(1)
(root);
const treemap_domain= root.descendants().filter(d=>d.depth==2).map(d=>d.data[0]);
//treemap_domain=root.copy().sort((a, b) => d3.ascending(a.data[0], b.data[0])).children.map(d => d.data[0])
return treemapDraw(root, treemap_domain);
}
Insert cell
function treemapDraw(treeRoot, treemap_domain){
var margin = {top: 0, right: 0, bottom: 0, left: 0},
width1 = 700 - margin.left - margin.right,
height1 = 450 - margin.top - margin.bottom;

const svg2 = d3.create("svg")
.attr("viewBox", [-margin.Left, -margin.Top, width1, height1])
.attr("width", width1)
.attr("height", height1)
.attr("style", "max-width: 100%; height: auto; height: intrinsic;")
.attr("font-family", "sans-serif")
.attr("font-size", 10);
// color scale
const op_domain= d3.extent(treeRoot.descendants().filter(d=>d.depth==2).map(d1=>d1.value))
const color = d3.scaleOrdinal()
.domain(treemap_domain)
.range(d3.schemeBlues)
//.range(['#F6A1F9', '#87ABBB', '#412433', '#56B870',
// '#FDAB41', '#64624F', '#BCD32F', '#75EDB8',
// "#89EE4B", '#AD4FE8', '#D5AB61', '#BC3B3A'])
const opacity = d3.scaleLinear()
.domain(op_domain)
.range([0,1])
// Creating rectangles for each state:
svg2.append("g")
.selectAll("rect")
.data(treeRoot.descendants().filter(d=>d.depth==2))
.enter()
.append("rect")
.attr('x', d=> d.x0)
.attr('y', d=> d.y0)
.attr('width', d=> (d.x1 - d.x0))
.attr('height', d=>(d.y1 - d.y0))
.style("stroke", "black")
.style("fill", d=> color(d.data[0])) //citation years
//.style("fill", function(d){ return color(d.parent.data.name)} )
.style("opacity", d=> opacity(d.value))
//root.leaves().map(d=>d.parent.data[0] )
//Adding the State labels
svg2.append('g')
.selectAll("text")
.data(treeRoot.descendants().filter(d=>d.depth==2))
.enter()
.append("text")
.attr("x", d=> d.x0+(d.x1 - d.x0)/2-10)
.attr("y", d=>d.y0+(d.y1 - d.y0)/2)
.text(d=>d.data[0])
.attr("font-size", "10px")
.attr("fill", "Orange" );

svg2
.selectAll("vals")
.data(treeRoot.descendants().filter(d=>d.depth==2))
.enter()
.append("text")
.attr("x", d=> d.x0+(d.x1 - d.x0)/2-10+5)
.attr("y", d=>d.y0+(d.y1 - d.y0)/2+10) // +10 to adjust position (more right)
// +20 to adjust position (lower)
.text(d=>d.value )
.attr("font-size", "8px")
.attr("fill", "green")
//Adding the Region labels
svg2 .append('g')
.selectAll("titles")
.data(treeRoot.descendants().filter(d=> d.depth==1))
.enter()
.append("text")
.attr("x", d=> d.x0+(d.x1 - d.x0)/2-20)
.attr("y", d=>d.y0+(d.y1 - d.y0)/2)
.text(d => d.data[0] )
.attr("font-size", "14px")
.attr("fill", "White" );
return svg2.node();
}
Insert cell
treeMap()
Insert cell
date1=new Date("2008-12-01 00:00:00+00:00") //new Date("2008-12-01 00:00:00+00:00").toLocaleDateString('en-CA')
Insert cell
date2= new Date("2003-08-01")
Insert cell
date1.toISOString()
Insert cell
day_diff=(date2.getTime()-date1.getTime())/(1000*3600*24)
Insert cell
Insert cell
//typeof (d3.timeFormat("%Y-%m-%d")(date1))
Insert cell
//d3.timeParse("%y-%m-%d")(date1)
Insert cell
//root = d3.hierarchy(articles).count()
Insert cell
//root.descendants().filter(d=>d.depth==2).map(d=>d.value).sort((a, b) => b.height - a.height || b.value - a.value);
Insert cell
//root=d3.hierarchy(article).count().sort((a, b) => b.height - a.height || b.value - a.value);
Insert cell

//root.descendants().filter(d=>d.depth==2).map(d=>d.data)
Insert cell
//root.leaves()
Insert cell
//root.leaves().map(d=>{ var date= d.data["Policy citation date"];cite_dates.add(d3.timeFormat("%Y")(date))})
Insert cell
//citing_years=Array.from(cite_dates).sort((a,b)=>{return a-b})
Insert cell
//pub_dates.add(5)
Insert cell
//a.length
//root.descendants().filter(d=>d.depth==3).map(d=>d.data)
//root.leaves().map(d=>{ var date= d.data["Article publication date"];pub_dates.add(d3.timeFormat("%Y")(date))})
Insert cell
//root2.descendants().filter(d=>d.depth==2).map(d1=>d1.value)
Insert cell
//root2 = d3.hierarchy(article).count()
// .sort((a, b) => b.height - a.height || b.value - a.value);
Insert cell
// {const arr = [{"shape":"square","color":"red","used":1,"instances":1},{"shape":"square","color":"red","used":2,"instances":1},{"shape":"circle","color":"blue","used":0,"instances":0},{"shape":"square","color":"blue","used":4,"instances":4},{"shape":"circle","color":"red","used":1,"instances":1},{"shape":"circle","color":"red","used":1,"instances":0},{"shape":"square","color":"blue","used":4,"instances":5},{"shape":"square","color":"red","used":2,"instances":1}];

// const result = [...arr.reduce((r, o) => {
// const key = o.shape + '-' + o.color;
// const item = r.get(key) || Object.assign({}, o, {
// used: 0,
// instances: 0
// });
// item.used += o.used;
// item.instances += o.instances;

// return r.set(key, item);
// }, new Map).values()];

// return result;
// }
Insert cell
// treemap2 = d3.treemap()
// .tile(d3.treemapSquarify)
// .size([700, 450])
// .padding(0)
// (root2);
Insert cell
//x=root.descendants().filter(d=> d.depth==2) //citation level
Insert cell
// color1 = d3.scaleSequential()
// .domain(cite_years)
// .range(d3.schemeBlues)
Insert cell
//x.map(d=>d.data[0])// citation years
Insert cell
//root.leaves()
Insert cell
// Plot.dot(
// tableData,
// Plot.reverse(
// Plot.sort(
// "citingPolicyCount",
// Plot.binY(
// { r: "count" },
// {
// x: "publicationYear",
// y: "citingPolicyCount",
// fill: "citingPolicyCount",
// thresholds: 30
// }
// )
// )
// )
// ).plot()


// marks: [
// Plot.dot(tableData, { x: "publicationYear", y: "publicationCount", stroke: "publicationCount", marker: "circle" }),
// Plot.dot(tableData, { x: "publicationYear", y: "totalCitingPolicyCount", stroke: "totalCitingPolicyCount", marker: "circle" })
// ]
Insert cell
// Plot.plot({
// color: {legend: true},
// x: {
// label: null
// },
// y: {
// grid: true,
// label: "↑ Count"
// },
// marks: [
// Plot.ruleY([0]),
// Plot.dot(tableData, {
// x: "publicationYear",
// y: "publicationCount",
// //z: "citationYear",totalCitingPolicyCount
// stroke: "publicationCount"
// }),
// Plot.dot(tableData, {
// x: "publicationYear",
// y: "totalCitingPolicyCount",
// //z: "citationYear",totalCitingPolicyCount
// stroke: "totalCitingPolicyCount"
// })

// ]
// })
Insert cell
// [...article1.keys()].map(d=>
// article1.get(d).map(d1=>
// //{
// v.set(d,d1["Cited by title"])
// // v.set(key,((d1["Policy citation date"].getTime()-d1["Article publication date"].getTime()) /(1000*3600*24))) }
// // filteredArticles.map((d2,i)=>
// // d2.citaionLag=
// // ((d1["Policy citation date"].getTime()-d1["Article publication date"].getTime()) /(1000*3600*24))
// // )
// )
// )
//.keys()].map(d1=> crop_production.map((d,i)=>d["Region"]=regionMapping.get(d.State))[...articles.get(d).get(d1).keys()].map(d3=>articles.get(d).get(d1).get(d3))))//map((d2,i)=>i)))//(d2.map(d3=>d3)))))
Insert cell
// {

// const map = new Map()
// // map.set([0, 0], 'A')
// // const keyZ = [2, 2]
// // map.set(keyZ, 'Z')
// // console.log(map.get([0, 0])) // will not find
// // console.log(map.get(keyZ)) // will output Z
// const keyA = [0, 0]
// map.set('A',[])
// return map.get(keyA) //
// }


// {

// //const MultiKeyMap = require('multikeymap');
// const map = new MultiKey();
// //map.set(['a', 'b', 'c'], '123');
// // console.log( map.get(['a', 'b', 'c']) ); // 123
// // console.log( map.get(['b', 'a', 'c']) ); // 123
// // console.log( map.get(['c', 'a', 'b']) ); // 123
// // console.log( map.get(['b', 'a']) ); // undefined
// }
Insert cell
// Plot.plot({
// width: 900,
// height: 600,
// marginTop: 40,
// marginBottom: 80,
// marginLeft: 60,
// inset: 8,
// grid: false,
// color: {
// legend: true,
// },
// marks: [
// Plot.ruleY([0]),
// Plot.dot(filteredarticles2, {x: "citationSerial", y: "citaionLag",stroke: "citaionLag"
// })
// ]

// marks: [
// Plot.ruleX([1]),
// Plot.areaY(filteredarticles2, Plot.normalizeY({
// x: "citationSerial",
// y: "citaionLag",
// stroke: "citaionLag",
// marker: "circle"
// })),
// Plot.text(tableData, Plot.selectLast(Plot.normalizeY({
// x: "citationSerial",
// y: "citaionLag",
// z: "citaionLag",
// text: "citationSerial",
// textAnchor: "start",
// dx: 3
// })))
// ]
// })
Insert cell
// plot2 = ({
// mark:{
// type:"boxplot",
// ticks:true,
// },
// data:{
// values:tableData
// },
// encoding:{
// y:{field:"citingPolicyCount",type:"quantitative"},
// x:{field:"publicationYear",type:"nominal"},
// color:{field:"citationYear",type:"nominal", scale:{range:["blue","red"]}}
// }
// })
Insert cell
// vl.markBoxplot()
// .data(tableData)
// .encode(
// vl.x().fieldN("publicationYear"),
// vl.y().fieldQ("citingPolicyCount"),
// vl.color().fieldN("citationYear"),
// //vl.color().average("citingPolicyCount"),
// vl.tooltip().fieldQ("citingPolicyCount"),
// )
// .render()
Insert cell
// Plot.plot({
// width: 900,
// height: 600,
// marginTop: 40,
// marginBottom: 80,
// marginLeft: 60,
// inset: 8,
// grid: false,
// color: {
// legend: true,
// },
// marks: [
// Plot.ruleY([0]),
// Plot.dot(filteredarticles2, {x: "citationSerial", y: "citaionLag",stroke: "citaionLag"
// })
// ]
// })
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more