Triad sou.

"..count.. + facet_grid" の挙動について

追記

ggplot-0.9.1 で修正されていました!
ggplot-0.9.1 での実行結果

メモ

スクリプトの書き方が良くないのかもしれませんが、..count..facet_gridを併用したときの挙動をメモっておきます。
バージョンは R-2.15.0 + ggplot-0.9.0 です。


こう書くと全ての度数が 1 になってしまう。

require("ggplot2")

mydf1 <- data.frame(
  x = sample(letters[1:2], 500, replace = T),
  y = sample(letters[10:11], 500, replace = T)
)

ggplot(mydf1, aes(x = x, y = ..count..)) +
  geom_bar() + facet_grid( ~ y) + opts(title = "..count.. + facet_grid")


facet_wrap の場合は意図したグラフが得られました。

ggplot(mydf1, aes(x = x, y = ..count..)) +
  geom_bar() + facet_wrap( ~ y) + opts(title = "..count.. + facet_wrap")


また、データフレームに id 変数を加えてみると facet_wrap の結果と一致しました。

mydf2 <- data.frame(
  mydf1,
  id = 1:500
)
ggplot(mydf2, aes(x = x, y = ..count..)) +
  geom_bar() + facet_grid( ~ y) + opts(title = "..count.. + facet_grid + id"))


何でだろう。
多分 ..count.. の挙動を良く理解していないからだろう。

行列のスカラー微分のメモ

$\mathbf{A}$, $\mathbf{B}$ について、スカラー $\theta$ で微分する場合を考える。
だたし、
\[
\mathbf{A}= \left\{ a_{ij} \right\}, \frac{\partial \mathbf{A}}{\partial \theta}= \left\{ \frac{\partial a_{ij}}{\partial \theta} \right\}
\] とし、$\mathbf{B}$ も同様に定義する。

行列積の微分

行列積 $\mathbf{A} \mathbf{B}$ が定義できる場合、
\[
\frac{\partial \mathbf{A}\mathbf{B}}{\partial \theta}= \frac{\partial \mathbf{A}}{\partial \theta}\mathbf{B} + \mathbf{A}\frac{\partial \mathbf{B}}{\partial \theta}
\]

逆行列微分

$\mathbf{A}$ が正方行列で逆行列が存在するならば、
\[
\frac{\partial \mathbf{A}^{-1}}{\partial \theta}= -\mathbf{A}^{-1} \frac{\partial \mathbf{A}}{\partial \theta} \mathbf{A}^{-1}
\]

逆行列微分の導出

\[
\begin{align*}
\frac{\partial \mathbf{A}\mathbf{A}^{-1}}{\partial \theta} &=
\frac{\partial \mathbf{I}}{\partial \theta} \\
\frac{\partial \mathbf{A}}{\partial \theta}\mathbf{A}^{-1} + \mathbf{A}\frac{\partial \mathbf{A}^{-1}}{\partial \theta} &=
\mathbf{0}\\
\mathbf{A}\frac{\partial \mathbf{A}^{-1}}{\partial \theta} &= -\frac{\partial \mathbf{A}}{\partial \theta}\mathbf{A}^{-1} \\
\frac{\partial \mathbf{A}^{-1}}{\partial \theta} &= -\mathbf{A}^{-1}\frac{\partial \mathbf{A}}{\partial \theta}\mathbf{A}^{-1}
\end{align*}
\]

正方行列 $\mathbf{A}$, $\mathbf{B}$ について、
\[
\begin{align*}
\frac{\partial \mathbf{A}^{-1}\mathbf{B}\mathbf{A}^{-1}}{\partial \theta} &=
\frac{\partial \mathbf{A}^{-1}}{\partial \theta}\mathbf{B}\mathbf{A}^{-1} + \mathbf{A}^{-1}\frac{\partial \mathbf{B}\mathbf{A}^{-1}}{\partial \theta} \\ &= -\mathbf{A}^{-1}\frac{\partial \mathbf{A}}{\partial \theta}\mathbf{A}^{-1}\mathbf{B}\mathbf{A}^{-1} + \mathbf{A}^{-1}\frac{\partial \mathbf{B}}{\partial \theta}\mathbf{A}^{-1} - \mathbf{A}^{-1}\mathbf{B}\mathbf{A}^{-1}\frac{\partial \mathbf{A}}{\partial \theta}\mathbf{A}^{-1} \\ &=
\mathbf{A}^{-1} \left( \frac{\partial \mathbf{B}}{\partial \theta} -\frac{\partial \mathbf{A}}{\partial \theta}\mathbf{A}^{-1}\mathbf{B} -\mathbf{B}\mathbf{A}^{-1}\frac{\partial \mathbf{A}}{\partial \theta} \right) \mathbf{A}^{-1}
\end{align*}
\]

$\mathbf{A}$ の要素が全て定数の場合、$\partial \mathbf{A} / \partial \theta = \mathbf{0}$ より $\mathbf{A}^{-1} (\partial \mathbf{B} / \partial \theta) \mathbf{A}^{-1}$。

ちらつかない JEditorPane クラス の setText メソッド

JEditorPane クラス の setText メソッド

public void setText(String t) {
  try {
    Document doc = getDocument();
    doc.remove(0, doc.getLength());
    if (t == null || t.equals("")) {
      return;
    }
    Reader r = new StringReader(t);
    EditorKit kit = getEditorKit();
    kit.read(r, doc, 0);
  } catch (IOException ioe) {
    UIManager.getLookAndFeel().provideErrorFeedback(JEditorPane.this);
  } catch (BadLocationException ble) {
    UIManager.getLookAndFeel().provideErrorFeedback(JEditorPane.this);
  }
}

のように実装されていて、いったんドキュメントをクリア

    Document doc = getDocument();
    doc.remove(0, doc.getLength());

してから、kit.read(r, doc, 0); する仕様です。


このせいで、Timer 中で回したりしていると、クリアしている部分が見えてしまうことがあって、画面がちらついてしまいます。
というわけで、

class ExtJEdit extends JEditorPane {
  public void setText(String t) {
    if (t == null || t.equals("")) {
      return;
    }
    Reader r = new StringReader(t);
    HTMLDocument doc = new HTMLDocument();
    HTMLEditorKit kit = new HTMLEditorKit();
    try {
      kit.read(r, doc, 0);
      this.setDocument(doc);
    } catch (IOException e) {
      UIManager.getLookAndFeel().provideErrorFeedback(this);
    } catch (BadLocationException e) {
      UIManager.getLookAndFeel().provideErrorFeedback(this);
    }
  }
}

こんな感じに変更してみたところ、ほぼちらつかなくなりました。

サンプル



ちらつかない場合もあるので、適当にボタンを押しまくってください。

New 'ByteCompile' field in the DESCRIPTION file

R 2.14.0 から DESCRIPTION ファイルに 'ByteCompile' フィールドを指定できるようになったらしい。
パッケージ中の R コードを自動的にバイトコンパイルしてくれるため、ものによっては高速化が見込めるという感じ。
試してみようかな。

The `ByteCompile' field controls if the package code is byte-compiled on installation: the default is currently not to, so this may be useful for a package known to benefit particularly from byte-compilation (which can take quite a long time and increases the installed size of the package).

Writing R Extensions / 1.1.1 The DESCRIPTION file

リンク

JTextArea to JTable / JTable to JTextArea

Java Swing でテキストエリア \Leftrightarrow テーブルの例を作ってみました。
csv っぽい形式で JTextArea 入力されているデータを JTable に読み込んだり、JTable のデータを csv っぽい形式に掃き出す事ができます。


ポイント

最初に作成した JTable クラス型のオブジェクト tableFirstnew JTable(data) 等を代入しても、テーブルの更新ができません。

// not work
JTable tableFirst = new JTable(datamatrixFirst, colnameFirst);
tableFirst = new JTable(datamatrixSecond, colnameSecond);


TableModel クラス型のオブジェクト tableModel で初期化し、tableModel の方を setDataVector メソッドで編集してあげると、テーブルがちゃんと更新されます。

// work
DefaultTableModel tableModel =
  new DefaultTableModel(datamatrixFirst, colnameFirst);

JTable tableFirst = new JTable(tableModel);
tableModel.setDataVector(datamatrixSecond, colnameSecond);

ソースコード

import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.JTable;
import java.awt.Rectangle;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;

import javax.swing.JScrollPane;
import javax.swing.table.DefaultTableModel;
import javax.swing.JButton;

public class myTable {

  /**
  * @param args
  */
  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
        myTable application = new myTable();
        application.getJFrame().setVisible(true);
      }
    });
  }

  private String[] colName = {"x", "pdf", "cdf"};
  private Double[][] dataMatrix = {
    { -3.0, 0.00443, 0.00443},
    { -2.5, 0.01753, 0.01753},
    { -2.0, 0.05399, 0.05399},
    { -1.5, 0.12952, 0.12952},
    { -1.0, 0.24197, 0.24197},
    { -0.5, 0.35207, 0.35207},
    { 0.0, 0.39894, 0.39894},
    { 0.5, 0.35207, 0.35207},
    { 1.0, 0.24197, 0.24197},
    { 1.5, 0.12952, 0.12952},
    { 2.0, 0.05399, 0.05399},
    { 2.5, 0.01753, 0.01753},
    { 3.0, 0.00443, 0.00443}
  };
  private JTable dataTable = null;
  private JButton jButtonTable2Text = null;
  private JButton jButtonText2Table = null;
  private JPanel jContentPane = null;
  private JFrame jFrame = null;
  private JScrollPane jScrollPane = null;
  private JScrollPane jScrollPaneTextArea = null;

  public DefaultTableModel tableModel =
    new DefaultTableModel(dataMatrix, colName);
  public JTextArea tableText = null;

  /**
  * This method initializes dataTable
  *
  * @return javax.swing.JTable
  */
  private JTable getDataTable() {
    if (dataTable == null) {
      dataTable = new JTable(tableModel);
    }
    return dataTable;
  }

  /**
  * This method initializes jButtonTable2Text
  *
  * @return javax.swing.JButton
  */
  private JButton getJButtonTable2Text() {
    if (jButtonTable2Text == null) {
      jButtonTable2Text = new JButton();
      jButtonTable2Text.setBounds(new Rectangle(315, 135, 61, 31));
      jButtonTable2Text.setText("←");
      jButtonTable2Text.addActionListener(new java.awt.event.ActionListener() {
        @Override
        public void actionPerformed(java.awt.event.ActionEvent e) {
          textUpdate();
        }
      });
    }
    return jButtonTable2Text;
  }

  /**
  * This method initializes jButtonText2Table
  *
  * @return javax.swing.JButton
  */
  private JButton getJButtonText2Table() {
    if (jButtonText2Table == null) {
      jButtonText2Table = new JButton();
      jButtonText2Table.setBounds(new Rectangle(315, 90, 61, 31));
      jButtonText2Table.setText("→");
      jButtonText2Table.addActionListener(new java.awt.event.ActionListener() {
        @Override
        public void actionPerformed(java.awt.event.ActionEvent e) {
          tableUpdate();
        }
      });
    }
    return jButtonText2Table;
  }

  /**
  * This method initializes jContentPane
  *
  * @return javax.swing.JPanel
  */
  private JPanel getJContentPane() {
    if (jContentPane == null) {
      jContentPane = new JPanel();
      jContentPane.setLayout(null);
      jContentPane.add(getJScrollPane(), null);
      jContentPane.add(getJButtonText2Table(), null);
      jContentPane.add(getJButtonTable2Text(), null);
      jContentPane.add(getJScrollPaneTextArea(), null);
      textUpdate();
    }
    return jContentPane;
  }

  /**
  * This method initializes jFrame
  *
  * @return javax.swing.JFrame
  */
  private JFrame getJFrame() {
    if (jFrame == null) {
      jFrame = new JFrame();
      jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      jFrame.setSize(684, 283);
      jFrame.setContentPane(getJContentPane());
      jFrame.setTitle("Application");
    }
    return jFrame;
  }

  /**
  * This method initializes jScrollPane
  *
  * @return javax.swing.JScrollPane
  */
  private JScrollPane getJScrollPane() {
    if (jScrollPane == null) {
      jScrollPane = new JScrollPane();
      jScrollPane.setBounds(new Rectangle(390, 15, 271, 226));
      jScrollPane.setViewportView(getDataTable());
    }
    return jScrollPane;
  }

  /**
  * This method initializes jScrollPaneTextArea
  *
  * @return javax.swing.JScrollPane
  */
  private JScrollPane getJScrollPaneTextArea() {
    if (jScrollPaneTextArea == null) {
      jScrollPaneTextArea = new JScrollPane();
      jScrollPaneTextArea.setBounds(new Rectangle(15, 15, 286, 226));
      jScrollPaneTextArea.setViewportView(getTableText());
    }
    return jScrollPaneTextArea;
  }

  /**
  * This method initializes tableText
  *
  * @return javax.swing.tableText
  */
  private JTextArea getTableText() {
    if (tableText == null) {
      tableText = new JTextArea();
    }
    return tableText;
  }

  private void tableUpdate() {

    BufferedReader textInput = new BufferedReader(new StringReader(
          tableText.getText()
        ));

    ArrayList<String[]> list = new ArrayList<String[]>();
    String line = null;
    String[] arrayline = null;

    try {

      while ((line = textInput.readLine()) != null) {
        arrayline = line.split(",");
        list.add(arrayline);
      }
      textInput.close();

      String[] colName = list.get(0);

      list.remove(0);
      String[][] dataMatrix = list.toArray(new String[0][0]);

      tableModel.setDataVector(dataMatrix, colName);

    } catch (IOException e) {

    }

  }

  private void textUpdate() {

    String textUpdated = "";

    for (int j = 0; j < tableModel.getColumnCount(); j++) {
      if (j != tableModel.getColumnCount() - 1) {
        textUpdated =
          textUpdated + tableModel.getColumnName(j) + ",";
      } else {
        textUpdated =
          textUpdated + tableModel.getColumnName(j) + "\n";
      }
    }

    for (int i = 0; i < tableModel.getRowCount(); i++) {
      for (int j = 0; j < tableModel.getColumnCount(); j++) {
        if (j != tableModel.getColumnCount() - 1) {
          textUpdated =
            textUpdated + tableModel.getValueAt(i, j) + ",";
        } else {
          textUpdated =
            textUpdated + tableModel.getValueAt(i, j) + "\n";
        }
      }
    }

    tableText.setText(textUpdated);

  }

}