Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
191 changes: 110 additions & 81 deletions DashAI/front/src/components/notebooks/dataset/tabs/CorrelationsTab.jsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,48 @@
import React from "react";
import React, { useMemo } from "react";
import { Box, Typography, CardContent, Card } from "@mui/material";
import { useTheme } from "@mui/material/styles";
import {
BarChart,
Bar,
Cell,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
ResponsiveContainer,
} from "recharts";
import Plot from "react-plotly.js";
import { useTranslation } from "react-i18next";

const CorrelationsTab = ({ correlations }) => {
const { t } = useTranslation(["datasets"]);

const theme = useTheme();
const corrData = [];
Object.entries(correlations).forEach(([col1, corrs]) => {
Object.entries(corrs).forEach(([col2, value]) => {
if (col1 < col2) {
// Avoid duplicates
corrData.push({
pair: `${col1} - ${col2}`,
correlation: value,
});
}

const { columns, zValues, strongCorrelations, leftMargin } = useMemo(() => {
const cols = Object.keys(correlations);

// Build symmetric matrix
const z = cols.map((col1) =>
cols.map((col2) => {
if (col1 === col2) return 1;
return correlations[col1]?.[col2] ?? correlations[col2]?.[col1] ?? 0;
}),
);

// Extract strong correlations (|r| > 0.5, no self-correlations)
const strong = [];
cols.forEach((col1, i) => {
cols.forEach((col2, j) => {
if (i < j && Math.abs(z[i][j]) > 0.5) {
strong.push({
pair: `${col1} - ${col2}`,
correlation: z[i][j],
});
}
});
});
});
strong.sort((a, b) => Math.abs(b.correlation) - Math.abs(a.correlation));

corrData.sort((a, b) => Math.abs(b.correlation) - Math.abs(a.correlation));
const maxLabelLen = Math.max(...cols.map((c) => c.length), 0);
const leftMargin = Math.min(maxLabelLen * 7 + 20, 300);

return {
columns: cols,
zValues: z,
strongCorrelations: strong,
leftMargin,
};
}, [correlations]);

return (
<Card>
Expand All @@ -40,74 +52,91 @@ const CorrelationsTab = ({ correlations }) => {
</Typography>

<Box mb={4}>
<ResponsiveContainer width="100%" height={300}>
<BarChart data={corrData}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="pair" angle={-45} textAnchor="end" height={100} />
<YAxis domain={[-1, 1]} />
<Tooltip
contentStyle={{
backgroundColor: theme.palette.background.paper,
borderRadius: 4,
<Plot
data={[
{
z: zValues,
x: columns,
y: columns,
type: "heatmap",
colorscale: [
[0, theme.palette.error.main],
[0.5, theme.palette.background.paper],
[1, theme.palette.success.main],
],
zmin: -1,
zmax: 1,
text: zValues.map((row) => row.map((val) => val.toFixed(3))),
texttemplate: "%{text}",
textfont: {
color: theme.palette.text.primary,
}}
labelStyle={{ color: theme.palette.text.primary }}
/>
<Bar
dataKey="correlation"
name={t("datasets:label.correlation")}
fill={theme.palette.info.main}
>
{corrData.map((entry, index) => (
<Cell
key={index}
fill={
entry.correlation > 0
? theme.palette.success.main
: theme.palette.error.main
}
/>
))}
</Bar>
</BarChart>
</ResponsiveContainer>
size: 11,
},
hovertemplate: "%{x} — %{y}<br>r = %{z:.3f}<extra></extra>",
showscale: true,
colorbar: {
title: {
text: "r",
font: { color: theme.palette.text.primary },
},
tickfont: { color: theme.palette.text.secondary },
},
},
]}
layout={{
autosize: true,
height: Math.max(400, columns.length * 40 + 150),
margin: { l: leftMargin, r: 40, t: 20, b: 120 },
paper_bgcolor: "rgba(0,0,0,0)",
plot_bgcolor: "rgba(0,0,0,0)",
xaxis: {
tickangle: -45,
tickfont: { color: theme.palette.text.secondary, size: 11 },
side: "bottom",
},
yaxis: {
tickfont: { color: theme.palette.text.secondary, size: 11 },
autorange: "reversed",
},
}}
config={{ displayModeBar: false, responsive: true }}
useResizeHandler
style={{ width: "100%" }}
/>
</Box>

<Box>
<Typography variant="h6" fontWeight="bold" mb={2}>
{t("datasets:label.strongCorrelations")} (|r| &gt; 0.5)
</Typography>
<Box display="flex" flexDirection="column" gap={1}>
{corrData
.filter((d) => Math.abs(d.correlation) > 0.5)
.map((d, idx) => (
<Box
key={idx}
display="flex"
alignItems="center"
justifyContent="space-between"
p={2}
{strongCorrelations.map((d, idx) => (
<Box
key={idx}
display="flex"
alignItems="center"
justifyContent="space-between"
p={2}
sx={{
backgroundColor: theme.palette.ui.panelMedium,
borderRadius: 2,
}}
>
<Typography variant="body2" fontWeight={500}>
{d.pair}
</Typography>
<Typography
variant="body2"
fontWeight="bold"
sx={{
backgroundColor: theme.palette.ui.panelMedium,
borderRadius: 2,
color: d.correlation > 0 ? "success.main" : "error.main",
}}
>
<Typography variant="body2" fontWeight={500}>
{d.pair}
</Typography>
<Typography
variant="body2"
fontWeight="bold"
sx={{
color: d.correlation > 0 ? "success.main" : "error.main",
}}
>
{d.correlation.toFixed(3)}
</Typography>
</Box>
))}
{corrData.filter((d) => Math.abs(d.correlation) > 0.5).length ===
0 && (
{d.correlation.toFixed(3)}
</Typography>
</Box>
))}
{strongCorrelations.length === 0 && (
<Box p={2}>
<Typography
variant="body2"
Expand Down
15 changes: 12 additions & 3 deletions DashAI/front/src/components/notebooks/dataset/tabs/OverviewTab.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,17 +102,26 @@ const OverviewTab = ({
{t("datasets:label.missingValuesOverview")}
</Typography>
<Chip
label={`Total: ${Object.values(nan).reduce((sum, v) => sum + v, 0)}`}
label={`Total: ${Object.values(nan).reduce(
(sum, v) => sum + v,
0,
)}`}
size="small"
variant="outlined"
sx={{ fontWeight: "bold" }}
/>
</Box>
<Box sx={{ width: "100%", height: 300 }}>
<ResponsiveContainer width="100%" height="100%">
<BarChart data={missingData}>
<BarChart data={missingData} margin={{ bottom: 120 }}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="column" />
<XAxis
dataKey="column"
angle={-45}
textAnchor="end"
interval={0}
tick={{ fontSize: 11, fill: theme.palette.text.secondary }}
/>
<YAxis />
<Tooltip
contentStyle={{
Expand Down
Loading