我有一个形状为(N,)的值arr
数组和一个形状为(N,2)的坐标coords
数组。我想在(M,M)数组grid
中表示它,使得grid
在coords
中不在的坐标处取值0,对于包含的坐标,它应该将所有具有该坐标的值的和存储在arr
中。因此,如果M = 3,arr = np.arange(4)+1
和coords = np.array([[0,0,1,2],[0,0,2,2]])
,则grid
应该是:
array([[3., 0., 0.],
[0., 0., 3.],
[0., 0., 4.]])
之所以如此,是因为我需要多次重复此步骤,arr
中的值每次都会更改,因此坐标也会更改。理想情况下,我正在寻找矢量化解决方案。我怀疑我可以以某种方式使用np.where
,但如何使用尚不是很明显。
为解决方案计时
我已对当前出现的解决方案进行了计时,看来累加器方法比稀疏矩阵方法稍快,而第二种累加方法由于注释中所述的原因最慢:
%timeit for x in range(100): accumulate_arr(np.random.randint(100,size=(2,10000)),np.random.normal(0,1,10000))
%timeit for x in range(100): accumulate_arr_v2(np.random.randint(100,size=(2,10000)),np.random.normal(0,1,10000))
%timeit for x in range(100): sparse.coo_matrix((np.random.normal(0,1,10000),np.random.randint(100,size=(2,10000))),(100,100)).A
47.3 ms ± 1.79 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
103 ms ± 255 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
48.2 ms ± 36 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
答案 0 :(得分:3)
一种方法是创建一个sparse.coo_matrix
并将其转换为密集型:
from scipy import sparse
sparse.coo_matrix((arr,coords),(M,M)).A
# array([[3, 0, 0],
# [0, 0, 3],
# [0, 0, 4]])
答案 1 :(得分:2)
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class SnakeGame {
private JFrame frame;
private Snake snake;
private JPanel buttonsPane;
private JButton[] buttons; // Our array of buttons
private Timer timer;
private Direction currentDirection;
// This enum will be used to determine the direction the snake will take.
private enum Direction {
TOP, LEFT, BOTTOM, RIGHT
}
public static void main(String[] args) {
// We place our program on the EDT using Java 8 lambda expressions.
SwingUtilities.invokeLater(() -> new SnakeGame().createAndShowGUI());
}
private void createAndShowGUI() {
frame = new JFrame(getClass().getSimpleName());
snake = new Snake();
buttonsPane = new JPanel();
buttons = new JButton[Direction.values().length];
for (int i = 0; i < buttons.length; i++) {
buttons[i] = new JButton(Direction.values()[i].toString()); // We create a JButton with the current value of the direction
buttons[i].addActionListener(listener); // We set their ActionListeners
buttonsPane.add(buttons[i]); // And add them to the buttonsPane
}
currentDirection = Direction.RIGHT; // We set a default direction
timer = new Timer(1000, listener); // And start our Swing Timer
// We add our components and then pack the frame, after that we start the timer.
frame.add(snake);
frame.add(buttonsPane, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
timer.start();
}
// Our ActionListener for moving the snake
private ActionListener listener = e -> { // Using Java 8 lambda expressions again
// We set the current direction using a ternary, if the source of the event is
// the timer we leave the current direction as is
// otherwise we set it to the direction from the button clicked
currentDirection = e.getSource().equals(timer) ? currentDirection : Direction.valueOf(e.getActionCommand());
snake.move(currentDirection); // And we call the move method
};
@SuppressWarnings("serial")
class Snake extends JPanel {
private int xPos;
private int yPos;
private static final int SPEED = 10; // We set the speed as a constant (10 pixels at a time) in any direction
// We determine the movement direction
public void move(Direction direction) {
switch (direction) {
case TOP:
yPos -= SPEED;
break;
case LEFT:
xPos -= SPEED;
break;
case BOTTOM:
yPos += SPEED;
break;
case RIGHT:
xPos += SPEED;
break;
}
this.repaint(); // And repaint the snake
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.DARK_GRAY);
g2d.fill(new Rectangle2D.Double(xPos, yPos, 10, 10)); // We draw a rectangle using the Shape API
}
@Override
public Dimension getPreferredSize() {
return new Dimension(300, 300); // We set the preferredSize of the JPanel to 300 x 300
}
}
}
样品运行-
ActionListener
另一个与def accumulate_arr(coords, arr):
# Get output array shape
m,n = coords.max(1)+1
# Get linear indices to be used as IDs with bincount
lidx = np.ravel_multi_index(coords, (m,n))
# Or lidx = coords[0]*(coords[1].max()+1) + coords[1]
# Accumulate arr with IDs from lidx
return np.bincount(lidx,arr,minlength=m*n).reshape(m,n)
相似的行,可能更容易理解-
In [58]: arr
Out[58]: array([1, 2, 3, 4])
In [59]: coords
Out[59]:
array([[0, 0, 1, 2],
[0, 0, 2, 2]])
In [60]: accumulate_arr(coords, arr)
Out[60]:
array([[3., 0., 0.],
[0., 0., 3.],
[0., 0., 4.]])