gpt4 book ai didi

javascript - R传单中的饼图,将计数变为总和并控制更多大小

转载 作者:行者123 更新时间:2023-12-05 00:29:11 33 4
gpt4 key购买 nike

我对分组标记和以小饼图形式按组显示计数的解决方案很着迷https://stackoverflow.com/a/60525137/3480717
我只是R,不知道JS。我希望代码对每个数据点的值求和而不是计数(每个单独的数据点可能已经代表一个计数)。而且我想根据值控制更多气泡的大小。
你能帮我看看如何更改 js 代码,以便它对数据点的值求和,以及如何增加/控制气泡的大小吗?
这里有一个对非饼标记求和而不是计数的理想解决方案:How to display the value (sum) rather than count of markers in a dc.leaflet.js
这里有一个也可以控制气泡大小的解决方案:Clustered leaflet markers with sum (not count) totals: how to get consistent round red shape and label format like in unclustered markers
原码是https://stackoverflow.com/users/2711712/danielbonnery @DanielBonnery

library(leaflet)
library(dplyr)
#Creates data
data("breweries91",package="leaflet")
#set.seed(1);
breweries91$goodbear<-sample(as.factor(c("terrific","marvelous","culparterretaping")),nrow(breweries91),replace=T)
#Colors
joliepalette<-c("red","green","blue")[1:nlevels(breweries91$goodbear)]
getColor <- function(breweries91) {joliepalette[breweries91$goodbear]}

icons <- awesomeIcons(
icon = 'ios-close',
iconColor = 'black',
library = 'ion',
markerColor = getColor(breweries91)
)

#Generate the javascript

jsscript3<-
paste0(
"function(cluster) {
const groups= [",paste("'",levels(breweries91$goodbear),"'",sep="",collapse=","),"];
const colors= {
groups: [",paste("'",joliepalette,"'",sep="",collapse=","),"],
center:'#ddd',
text:'black'
};
const markers= cluster.getAllChildMarkers();

const proportions= groups.map(group => markers.filter(marker => marker.options.group === group).length / markers.length);
function sum(arr, first= 0, last) {
return arr.slice(first, last).reduce((total, curr) => total+curr, 0);
}
const cumulativeProportions= proportions.map((val, i, arr) => sum(arr, 0, i+1));
cumulativeProportions.unshift(0);

const width = 2*Math.sqrt(markers.length);
const radius= 15+width/2;

const arcs= cumulativeProportions.map((prop, i) => { return {
x : radius*Math.sin(2*Math.PI*prop),
y : -radius*Math.cos(2*Math.PI*prop),
long: proportions[i-1] >.5 ? 1 : 0
}});
const paths= proportions.map((prop, i) => {
if (prop === 0) return '';
else if (prop === 1) return `<circle cx='0' cy='0' r='${radius}' fill='none' stroke='${colors.groups[i]}' stroke-width='${width}' stroke-alignment='center' stroke-linecap='butt' />`;
else return `<path d='M ${arcs[i].x} ${arcs[i].y} A ${radius} ${radius} 0 ${arcs[i+1].long} 1 ${arcs[i+1].x} ${arcs[i+1].y}' fill='none' stroke='${colors.groups[i]}' stroke-width='${width}' stroke-alignment='center' stroke-linecap='butt' />`
});

return new L.DivIcon({
html: `
<svg width='60' height='60' viewBox='-30 -30 60 60' style='width: 60px; height: 60px; position: relative; top: -24px; left: -24px;' >
<circle cx='0' cy='0' r='15' stroke='none' fill='${colors.center}' />
<text x='0' y='0' dominant-baseline='central' text-anchor='middle' fill='${colors.text}' font-size='15'>${markers.length}</text>
${paths.join('')}
</svg>
`,
className: 'marker-cluster'
});
}")

# Generates the map.
leaflet() %>%
addTiles() %>%
addAwesomeMarkers(data=breweries91,
group=~goodbear,
icon = icons,
clusterOptions = markerClusterOptions(
iconCreateFunction =
JS(jsscript3)))

最佳答案

I would like the code to sum values from each data point and not count.


您可以使用 markerOptions() 将数据/统计信息传递给标记。
leaflet() %>%
addTiles() %>%
addMarkers(
options = markerOptions(score = getScore(breweries91)),
...
)
然后在 JavaScript 中使用 marker.options.score检索它。

And I would like to control more the size of the bubbles dependent on the value.


在下面的演示代码中,在 javascript 中,查找代码 let width = 4 + 2*Math.sqrt(grandTotal/1.5);玩它来调整气泡半径。

... count for non-pie markers


可用,R 的传单,初始化器 makeIcon , awesomeIcons , 和 icons强制您创建和使用自定义图像。而且没有办法绕过它。 addCircleMarkers看起来对我们的目的很有用,但它不允许您设置文本。
我们可以使用 singleMarkerMode在集群选项中。使用它,我们可以使单个标记成为大小为 1 的簇,并使用我们已经编码的 iconCreateFunction 渲染它们JavaScript 代码:
leaflet() %>%
addTiles() %>%
addMarkers(
...
clusterOptions = markerClusterOptions(
singleMarkerMode = TRUE,
iconCreateFunction = JS(jsscript3)
)
)

1) 演示:在您的代码中,没有可用于标记的可用数字数据。所以我创建了一个映射,使用 getScore函数,对于分值:
terrific          => 3
marvelous => 2
culparterretaping => 1
使用 summarytools 添加带有摘要的图例.
这是最终代码:
# Title: R Leaflet custom summing marker demo


# Load packages ##################
install.packages("pacman")
require(pacman)

pacman::p_load(pacman, dplyr, leaflet, summarytools)


# Creates data ##################
data("breweries91",package="leaflet")
cat('\014') # ctrl+L
#head(breweries91, 2L)
breweries91$goodbeer<-sample(as.factor(c("terrific","marvelous","culparterretaping")),nrow(breweries91),replace=T)
names(breweries91)

# Colors
joliepalette<-c("darkviolet","orangered","lime")[1:nlevels(breweries91$goodbeer)]
getColor <- function(breweries91) {joliepalette[breweries91$goodbeer]}

# Score
jolieValue<-c(1L,2L,3L)[1:nlevels(breweries91$goodbeer)]
getScore <- function(breweries91) {jolieValue[breweries91$goodbeer]}


# iconCreateFunction Javascript
jsscript3<-paste0(
"function(cluster) {
const groups= [",paste("'",levels(breweries91$goodbeer),"'",sep="",collapse=","),"];
const colors= {
groups: [",paste("'",joliepalette,"'",sep="",collapse=","),"],
center:'#ddd',
text:'black'
};
const markers= cluster.getAllChildMarkers();
let grandTotal = markers.reduce((a,b)=> +a + +b.options.score, 0);

const proportions= groups.map(group => markers
.filter(marker => marker.options.group === group)
.reduce((a,b)=> +a + +b.options.score, 0) / grandTotal);

function sum(arr, first= 0, last) {
return arr.slice(first, last).reduce((total, curr) => total+curr, 0);
}
const cumulativeProportions= proportions.map((val, i, arr) => sum(arr, 0, i+1));
cumulativeProportions.unshift(0);

let width = 4 + 2*Math.sqrt(grandTotal/1.5);
width = width > 16? 16: width;
let radius= 10 + (width/2);
radius += (grandTotal < 40)? grandTotal/10 : 4;

const arcs= cumulativeProportions.map((prop, i) => { return {
x : radius*Math.sin(2*Math.PI*prop),
y : -radius*Math.cos(2*Math.PI*prop),
long: proportions[i-1] >.5 ? 1 : 0
}});
const paths= proportions.map((prop, i) => {
if (prop === 0) return '';
else if (prop === 1) return `<circle cx='0' cy='0' r='${radius-2}' fill-opacity='0.3' stroke-opacity fill='${colors.groups[i]}' stroke='${colors.groups[i]}' stroke-width='${width}' stroke-alignment='center' stroke-linecap='butt' />`;
else return `<path d='M ${arcs[i].x} ${arcs[i].y} A ${radius} ${radius} 0 ${arcs[i+1].long} 1 ${arcs[i+1].x} ${arcs[i+1].y}' fill='none' stroke='${colors.groups[i]}' stroke-width='${width}' stroke-alignment='center' stroke-linecap='butt' />`
});

return new L.DivIcon({
html: `
<svg width='60' height='60' viewBox='-30 -30 60 60' style='width: 60px; height: 60px; position: relative; top: -24px; left: -24px;' >
<circle cx='0' cy='0' r='15' stroke='none' fill='${colors.center}' />
${paths.join('')}
<text x='0' y='0' dominant-baseline='central' text-anchor='middle' fill='${colors.text}' font-size='16'>${grandTotal}</text>
</svg>
`,
className: 'marker-cluster'
});
}")

# gather stats for legend
myStat <- freq(breweries91$goodbeer, report.nas = FALSE, cumul = FALSE)
s1 <- paste("3 - terrific(",myStat[3,1],")")
s2 <- paste("2 - marvelous(",myStat[2,1],")")
s3 <- paste("1 - culparterretaping(", myStat[1,1],")")


# generates the map.
leaflet() %>%
addTiles() %>%
addLegend("topright",
colors = c("lime", "orangered", "darkviolet"),
labels = c(s1, s2,s3),
title = "Beer goodness:",
opacity = 1) %>%
addMarkers(data = breweries91,
group = ~goodbeer,
options = markerOptions(score = getScore(breweries91)),
clusterOptions = markerClusterOptions(
singleMarkerMode = TRUE,
iconCreateFunction = JS(jsscript3)
)
)


# print stats
freq(breweries91$goodbeer, report.nas = FALSE, cumul = FALSE)
print(paste("Grand Score: ", myStat[1,1]*1 + myStat[2,1]*2 + myStat[3,1]*3))


截屏:
enter image description here

2) 共享集群对象中的数据:每个标记都可以看到它的弹出对象和弹出选项。因此,您可以从标记对象本身中操作弹出窗口,在我们的例子中是 iconCreateFunction .

MarkerCluster库不提供为集群标记添加标签或弹出窗口的方法。当您单击群集图标时,它会放大并且不显示弹出窗口。作为一种解决方法,我们可以禁用点击放大并显示自定义工具提示/弹出窗口:

# Title: R Leaflet custom summing marker demo


# Load packages ##################
install.packages("pacman")
require(pacman)

pacman::p_load(pacman, dplyr, leaflet, summarytools)


# Creates data ##################
data("breweries91",package="leaflet")
cat('\014') # ctrl+L
#head(breweries91, 2L)
breweries91$goodbeer<-sample(as.factor(c("terrific","marvelous","culparterretaping")),nrow(breweries91),replace=T)
names(breweries91)

# Colors
joliepalette<-c("darkviolet","orangered","limegreen")[1:nlevels(breweries91$goodbeer)]
getColor <- function(breweries91) {joliepalette[breweries91$goodbeer]}

# Score
jolieValue<-c(1L,2L,3L)[1:nlevels(breweries91$goodbeer)]
getScore <- function(breweries91) {jolieValue[breweries91$goodbeer]}


# iconCreateFunction Javascript
jsscript3<-paste0(
"function(cluster) {
const groups= [",paste("'",levels(breweries91$goodbeer),"'",sep="",collapse=","),"];
const colors= {
groups: [",paste("'",joliepalette,"'",sep="",collapse=","),"],
center:'#ddd',
text:'black'
};
const markers= cluster.getAllChildMarkers();
let grandTotal = markers.reduce((a,b)=> +a + +b.options.score, 0);

const proportions= groups.map(group => markers
.filter(marker => marker.options.group === group)
.reduce((a,b)=> +a + +b.options.score, 0) / grandTotal);

function sum(arr, first= 0, last) {
return arr.slice(first, last).reduce((total, curr) => total+curr, 0);
}
const cumulativeProportions= proportions.map((val, i, arr) => sum(arr, 0, i+1));
cumulativeProportions.unshift(0);

let width = 4 + 2*Math.sqrt(grandTotal/1.5);
width = width > 16? 16: width;
let radius= 10 + (width/2);
radius += (grandTotal < 40)? grandTotal/10 : 4;

const arcs= cumulativeProportions.map((prop, i) => { return {
x : radius*Math.sin(2*Math.PI*prop),
y : -radius*Math.cos(2*Math.PI*prop),
long: proportions[i-1] >.5 ? 1 : 0
}});
const paths= proportions.map((prop, i) => {
if (prop === 0) return '';
else if (prop === 1) return `<circle cx='0' cy='0' r='${radius-2}' fill-opacity='0.3' stroke-opacity fill='${colors.groups[i]}' stroke='${colors.groups[i]}' stroke-width='${width}' stroke-alignment='center' stroke-linecap='butt' />`;
else return `<path d='M ${arcs[i].x} ${arcs[i].y} A ${radius} ${radius} 0 ${arcs[i+1].long} 1 ${arcs[i+1].x} ${arcs[i+1].y}' fill='none' stroke='${colors.groups[i]}' stroke-width='${width}' stroke-alignment='center' stroke-linecap='butt' />`
});

let icon = new L.DivIcon({
html: `
<svg width='60' height='60' viewBox='-30 -30 60 60' style='width: 60px; height: 60px; position: relative; top: -24px; left: -24px;' >
<circle cx='0' cy='0' r='15' stroke='none' fill='${colors.center}' />
${paths.join('')}
<text x='0' y='0' dominant-baseline='central' text-anchor='middle' fill='${colors.text}' font-size='16'>${grandTotal}</text>
</svg>
`,
className: 'marker-cluster'
});

// make custom popup for the cluster
if(cluster._map){
let counts = groups.map(group => markers
.filter(marker => marker.options.group === group).length);
let content = `<span style='color:limegreen'>${groups[2]}</span>&nbsp;<span>(${counts[2]})</span><br>`;
content += `<span style='color:orangered'>${groups[1]}</span>&nbsp;<span>(${counts[1]})</span><br>`;
content += `<span style='color:darkviolet'>${groups[0]}</span>&nbsp;<span>(${counts[0]})</span><br>`;
content = `<div style='font-size:13px;font-weight:bold'>` + content + `</div>`;

cluster.on('click', function (a) {
let tt = L.tooltip({permanent:false, direction:'top', offset: L.point(0, -width*2)});
tt.setContent( content );
tt.setLatLng(cluster.getLatLng());
tt.addTo(cluster._map);
});
}

return icon;
}")

# gather stats for legend
myStat <- freq(breweries91$goodbeer, report.nas = FALSE, cumul = FALSE)
s1 <- paste("3 - terrific(",myStat[3,1],")")
s2 <- paste("2 - marvelous(",myStat[2,1],")")
s3 <- paste("1 - culparterretaping(", myStat[1,1],")")


# generates the map.
leaflet() %>%
addTiles() %>%
addLegend("topright",
colors = c("limegreen", "orangered", "darkviolet"),
labels = c(s1, s2,s3),
title = "Beer goodness:",
opacity = 1) %>%
addMarkers(data = breweries91,
group = ~goodbeer,
popup = paste("", breweries91$goodbeer),
popupOptions = popupOptions(maxWidth = 1000, closeOnClick = TRUE),
options = markerOptions(score = getScore(breweries91)),
clusterOptions = markerClusterOptions(
singleMarkerMode = TRUE,
zoomToBoundsOnClick = FALSE,
iconCreateFunction = JS(jsscript3)
)
)


# print stats
cat('\014') # ctrl+L
freq(breweries91$goodbeer, report.nas = FALSE, cumul = FALSE)
print(paste("Grand Score: ", myStat[1,1]*1 + myStat[2,1]*2 + myStat[3,1]*3))

enter image description here
在这里,我们使用常规方法在单个标记上显示了弹出窗口:
leaflet() %>%
addTiles() %>%
addMarkers(data = breweries91,
popup = paste("", breweries91$goodbeer),
popupOptions = popupOptions(maxWidth = 1000, closeOnClick = TRUE),
...)
iconCreateFunction 中完成的特殊处理仅用于集群标记。

在最坏的情况下,如果您想在标记/集群之间共享数据,那么您可以找到 Leaflet map objectcluster._map属性(property)。或者您可以将数据附加到 javascript window对象并通过 javascript 代码在任何地方访问它。

3) 将整行传递给传单:我们可以使用以下方法将整行传递给传单:
options = markerOptions(row_data = setNames(split(breweries91,
seq(nrow(breweries91))),
rownames(breweries91)))
有了这个,我们现在可以在弹出窗口中有很多东西,包括坐标:

# Title: R Leaflet custom summing marker demo


# Load packages ##################
install.packages("pacman")
require(pacman)

pacman::p_load(pacman, dplyr, leaflet, summarytools)


# Creates data ##################
data("breweries91",package="leaflet")
cat('\014') # ctrl+L
#head(breweries91, 2L)
breweries91$goodbeer<-sample(as.factor(c("terrific","marvelous","culparterretaping")),nrow(breweries91),replace=T)
breweries91$score<-ifelse(breweries91$goodbeer == "terrific",3L,
ifelse(breweries91$goodbeer == "marvelous",2L,
ifelse(breweries91$goodbeer == "culparterretaping",1L,0L)))
names(breweries91)

# Colors
joliepalette<-c("darkviolet","orangered","limegreen")[1:nlevels(breweries91$goodbeer)]
getColor <- function(breweries91) {joliepalette[breweries91$goodbeer]}

# iconCreateFunction Javascript
jsscript3<-paste0(
"function(cluster) {
const groups= [",paste("'",levels(breweries91$goodbeer),"'",sep="",collapse=","),"];
const colors= {
groups: [",paste("'",joliepalette,"'",sep="",collapse=","),"],
center:'#ddd',
text:'black'
};
const markers= cluster.getAllChildMarkers();
//console.log(markers[0]);
let grandTotal = markers.reduce((a,b)=> +a + +b.options.row_data.data.score, 0);

const proportions= groups.map(group => markers
.filter(marker => marker.options.group === group)
.reduce((a,b)=> +a + +b.options.row_data.data.score, 0) / grandTotal);

function sum(arr, first= 0, last) {
return arr.slice(first, last).reduce((total, curr) => total+curr, 0);
}
const cumulativeProportions= proportions.map((val, i, arr) => sum(arr, 0, i+1));
cumulativeProportions.unshift(0);

let width = 4 + 2*Math.sqrt(grandTotal/1.5);
width = width > 16? 16: width;
let radius= 10 + (width/2);
radius += (grandTotal < 40)? grandTotal/10 : 4;

const arcs= cumulativeProportions.map((prop, i) => { return {
x : radius*Math.sin(2*Math.PI*prop),
y : -radius*Math.cos(2*Math.PI*prop),
long: proportions[i-1] >.5 ? 1 : 0
}});
const paths= proportions.map((prop, i) => {
if (prop === 0) return '';
else if (prop === 1) return `<circle cx='0' cy='0' r='${radius-2}' fill-opacity='0.3' stroke-opacity fill='${colors.groups[i]}' stroke='${colors.groups[i]}' stroke-width='${width}' stroke-alignment='center' stroke-linecap='butt' />`;
else return `<path d='M ${arcs[i].x} ${arcs[i].y} A ${radius} ${radius} 0 ${arcs[i+1].long} 1 ${arcs[i+1].x} ${arcs[i+1].y}' fill='none' stroke='${colors.groups[i]}' stroke-width='${width}' stroke-alignment='center' stroke-linecap='butt' />`
});

let icon = new L.DivIcon({
html: `
<svg width='60' height='60' viewBox='-30 -30 60 60' style='width: 60px; height: 60px; position: relative; top: -24px; left: -24px;' >
<circle cx='0' cy='0' r='15' stroke='none' fill='${colors.center}' />
${paths.join('')}
<text x='0' y='0' dominant-baseline='central' text-anchor='middle' fill='${colors.text}' font-size='16'>${grandTotal}</text>
</svg>
`,
className: 'marker-cluster'
});

// make custom popup for the cluster
let content ='popup';
if(cluster._map){ //if it's cluster
//console.log(cluster);
let counts = groups.map(group => markers
.filter(marker => marker.options.group === group).length);
content = `<span style='color:limegreen'>${groups[2]}</span>&nbsp;<span>(${counts[2]})</span><br>`;
content += `<span style='color:orangered'>${groups[1]}</span>&nbsp;<span>(${counts[1]})</span><br>`;
content += `<span style='color:darkviolet'>${groups[0]}</span>&nbsp;<span>(${counts[0]})</span><br>`;
content = `<div style='font-size:13px;font-weight:bold'>` + content + `</div>`;


} else{ //if it's single marker
//console.log(cluster.getAllChildMarkers());
cluster = cluster.getAllChildMarkers()[0];
//console.log(cluster);
let r = cluster.options.row_data;
let loc = r.coords;
r = r.data;
let address = r.address;
let name = `${r.brewery} (${r.founded})`;
content = `<span><strong>${name}</strong></span><br>`;
content += `<span style='margin-bottom:10px'>[${loc}]</span><hr>`;
content += `<span>${address}, ${r.village}, ${r.zipcode}</span><br>`;
content += `<span>Goodness: ${r.goodbeer}</span>`;
}
cluster.on('click', function (a) {
let tt = L.tooltip({permanent:false, direction:'top', offset: L.point(0, -width*2)});
tt.setContent( content );
tt.setLatLng(cluster.getLatLng());
tt.addTo(cluster._map);
});

return icon;
}")

# gather stats for legend
myStat <- freq(breweries91$goodbeer, report.nas = FALSE, cumul = FALSE)
s1 <- paste("3 - terrific(",myStat[3,1],")")
s2 <- paste("2 - marvelous(",myStat[2,1],")")
s3 <- paste("1 - culparterretaping(", myStat[1,1],")")


# generates the map.
leaflet() %>%
addTiles() %>%
addLegend("topright",
colors = c("limegreen", "orangered", "darkviolet"),
labels = c(s1, s2,s3),
title = "Beer goodness:",
opacity = 1) %>%
addMarkers(data = breweries91,
group = ~goodbeer,
popupOptions = popupOptions(maxWidth = 1000, closeOnClick = TRUE),
options = markerOptions(row_data = setNames(split(breweries91, seq(nrow(breweries91))), rownames(breweries91))),
clusterOptions = markerClusterOptions(
singleMarkerMode = TRUE,
zoomToBoundsOnClick = FALSE,
iconCreateFunction = JS(jsscript3)
)
)


# print stats
cat('\014') # ctrl+L
freq(breweries91$goodbeer, report.nas = FALSE, cumul = FALSE)
print(paste("Grand Score: ", myStat[1,1]*1 + myStat[2,1]*2 + myStat[3,1]*3))

enter image description here

作为引用,我提取了一个示例集群对象: Cluster Object Json .
使用它,您可以从集群对象中找到要在 javascript 中使用的属性。

关于javascript - R传单中的饼图,将计数变为总和并控制更多大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69880307/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com