Python Pandas 使いの私のための Clojure Tablecloth のメモ

2025/01/26に公開

Pandasでやるあの操作をClojure Tablecloth ではどうすればいいのかメモしてます。

※完成品ではありません。適宜更新します。

import / require

pandas

import pandas 

clojure

(ns sandbox
  (:require [tech.v3.dataset :as ds]
            [tech.v3.datatype.functional :as dfn]
            [tablecloth.api :as tc]
            [tech.v3.dataset.rolling :as ds-roll]))

read csv

pandas

df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/refs/heads/master/stockdata.csv")

clojure

(def stocks
  (tc/dataset "https://raw.githubusercontent.com/plotly/datasets/refs/heads/master/stockdata.csv"
              {:dataset-name :stocks}))

data info

pandas

df.info()

clojure

(tc/info stocks)

write csv

pandas

df.to_csv("/tmp/df.csv")

clojure

(tc/write! stocks "/tmp/stocks.csv")

select columns

pandas

df[["Date", "MSFT"]]

clojure

(ds/select-columns stocks ["Date" "MSFT"])

rolling

pandas

df["MSFT_MA3"] = df["MSFT"].rolling(window=3).mean()

clojure

(ds-roll/rolling stocks
                 {:window-size 3
                  :relative-window-position :left}
                 {:msft-ma3 (ds-roll/mean "MSFT")})
  • https://techascent.github.io/tech.ml.dataset/tech.v3.dataset.rolling.html

  • :relative-window-position :left :window-size のどの位置に計算したデータを入れるかを指定。

    (def x (ds/->dataset [{:b 10} {:b 20} {:b 30} {:b 40} {:b 50}]))
    ;; | :b |
    ;; |---:|
    ;; | 10 |
    ;; | 20 |
    ;; | 30 |
    ;; | 40 |
    ;; | 50 |
    

    left の場合、pandas と同じように window-size の最後に結果が入る

    (-> x
        (ds-roll/rolling {:window-size 3
                          :relative-window-position :left}
                         {:mean (ds-roll/mean :b)}))
    ;; _unnamed [5 2]:
    
    ;; | :b |       :mean |
    ;; |---:|------------:|
    ;; | 10 | 10.00000000 |
    ;; | 20 | 13.33333333 |
    ;; | 30 | 20.00000000 | ←上3行の結果がここに入る
    ;; | 40 | 30.00000000 |
    ;; | 50 | 40.00000000 |
    
    

    right の場合

    (-> x
        (ds-roll/rolling {:window-size 3
                          :relative-window-position :right}
                         {:mean (ds-roll/mean :b)}))
    ;; _unnamed [5 2]:
    
    ;; | :b |       :mean |
    ;; |---:|------------:|
    ;; | 10 | 20.00000000 |←下3行の結果がここに入る
    ;; | 20 | 30.00000000 |
    ;; | 30 | 40.00000000 |
    ;; | 40 | 46.66666667 |
    ;; | 50 | 50.00000000 |
    

    center の場合

    (-> x
        (ds-roll/rolling {:window-size 3
                          :relative-window-position :center}
                         {:mean (ds-roll/mean :b)}))
    ;; _unnamed [5 2]:
    
    ;; | :b |       :mean |
    ;; |---:|------------:|
    ;; | 10 | 13.33333333 |
    ;; | 20 | 20.00000000 |←上下3行の結果が真ん中に入る
    ;; | 30 | 30.00000000 |
    ;; | 40 | 40.00000000 |
    ;; | 50 | 46.66666667 |
    
    

rename columns

pandas

df.rename(columns={"MSFT": "MicroSoft"})

clojure

(ds/rename-columns stocks {"MSFT" :msft})

column operation

pandas

df["MSFT-GSPC"] = df["MSFT"] / df["GSPC"]

clojure

(tc// stocks :msft-gspc ["MSFT" "GSPC"])

sort-by / order-by

pandas

df.sort_values(by="Date") # 小さい方/古い方から順
df.sort_values(by="Date", ascending=False) # default True 

clojure

(tc/order-by stocks "Date" ) ;; 小さい方/古い方から順
(tc/order-by stocks "Date" :desc) ;; 逆 

drop duplicate

pandas

df.drop_duplicates()
df.drop_duplicates(subset = ["DATE"])

clojure

(tc/unique-by stocks)
(tc/unique-by stocks "Date")
(tc/unique-by stocks ["Date" "MSFT"])

fill zero

pandas

df['A'].replace(to_replace=0, method='ffill')

clojure

(defn fill-zero [data column]
  (->
   (tc/map-columns data column [column] #(if (= % 0.0) nil %))
   (tc/replace-missing [column] :down)))
  • ゼロは一旦 nil にしないとだめ

head / tail

pandas

df.head()
df.tail()

clojure

(tc/head DS)
(tc/tail DS)
(tc/tail DS 10)

一つのコラムデータに対する操作

pandas


df["MSFT"] - 1

clojure

(tc/update-columns DS :a #(dfn/- % 1)) ;; 特定のコラム
(tc/update-columns DS :all #(dfn/- % 1)) ;; 全てに対して

コラムの型変換

pandas

df.astype('int32').dtypes
df.astype({'col1': 'int32'}).dtypes

clojure

(-> DS
    (tc/convert-types :V1 :float64)
    (tc/info :columns))

<!--

read csv

pandas


clojure


-->

Discussion