'Cluster objects by geometric coordinates (Y axis)
I've got a pandas DataFrame with records describing rectangles with absolute coordinates of all the 4 points: TL (top-left), TR (top-right), BL (bottom-left) and BR (bottom-right). As it is, the rects seem to follow a row-like pattern, where there are conspicuous clusters forming "rows", like in this picture:
The data look like this:
tl_x tl_y tr_x tr_y br_x br_y bl_x bl_y ht wd
0 1567 136 1707 136 1707 153 1567 153 17 140
1 1360 154 1548 154 1548 175 1360 175 21 188
2 1567 154 1747 154 1747 174 1567 174 20 180
3 1311 175 1548 175 1548 196 1311 196 21 237
4 1565 174 1741 174 1741 199 1565 199 25 176
5 1566 196 1753 196 1753 220 1566 220 24 187
...
I need to cluster these objects along the bl_y
or br_y
column (bottom Y coordinate) to produce a 2D list of "rows" like:
As you see, objects in each "row" may have slightly varying Y coordinates (not exactly equivalent in each cluster). What I basically need is some function to add a separate e.g. clustered_y
column to the DF and then sort by this column.
What's the simplest way to go?
Solution 1:[1]
Following my comment on your question.
This is how you should be using a state variable.
function UserManagement({ history }) {
const dispatch = useDispatch();
const userList = useSelector((state) => state.userList);
useEffect(() => {
dispatch(getUsers());
},[dispatch, history]);
useEffect(() => {
console.log(userList);
},[userList]);
...
}
If you still need to create another variable, you need to assign it a value every time userList
changes - by adding this line to the useEffect
method just like this.
function UserManagement({ history }) {
const dispatch = useDispatch();
const userList = useSelector((state) => state.userList);
let users = userList;
useEffect(() => {
dispatch(getUsers());
},[dispatch, history]);
useEffect(() => {
users = userList;
},[userList]);
...
}
Notice that when you assign a value to a variable like this:
The value assigned to that variable is the initial value of the assigned variable (undefined) because the reducer has not yet updated the state value. And when it actually updates it, nothing updates the second variable you created "users
"
const userList = useSelector((state) => state.userList);
const users = userList;
And you can use it to manipulate your UI by:
{userList &&
userList.map((users) => (
<MyComponent/>
)
}
Solution 2:[2]
I added a comment to this question,so check that too.
However I just noticed something else that should help you.
Due the the way state works your users are probably returning as undefined
You have two choices here.
Change your
users.map()
touserList.users.map()
as userList.If you really want it to just be
users.map()
then you might have to use some react state. For example
import { useSelector } from 'react-redux';
import { useEffect, useState } from 'react';
import { MyUserComponent } from 'some_file';
const YourComponent = () => {
// grab your userList from redux
const userList = useSelector(state => state.userList);
// create some state for use the users
// an empty array to start
const [users, setUsers] = useState([]);
// watch the userList for changes
useEffect(() => {
// update the users state whenever
// there is a change to useList
setUsers(userlist.users)
}, [userList])
// do whatever you want in your return
return (
<div>
{
users.map(user => <MyUserComponent {...user} key={`user-${index}`}) />
}
</div>
)
}
Honestly I'd just do option 1
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Shaded |