Code Snippets
Convert Google Contacts CSV to Mutt Aliases python
import csv import pinyin csv_file = '~/google.csv' alias_file = '~/alias.txt' def zfc2string(zfc): string = pinyin.get(zfc, format='strip').replace(' ', '') return string with open(csv_file) as f: f_csv = csv.reader(f) headers = next(f_csv) for row in f_csv: name = zfc2string(row[0]).lower() first_name = row[1] last_name = row[3] email = row[28] if not name or not first_name or not email: print('Skipped: [name]=' + name + '; [email]=' + email) continue with open(alias_file, 'a+') as f: f.write('alias' + '\t') f.write(name + '\t') f.write(first_name) if last_name: f.write(' ' + last_name + '\t') else: f.write('\t') f.write('<' + email + '>' + '\n')
Python解析Kindle读书笔记 python
import re import codecs EOR = "==========" def parse(filename): clip_file = open(filename, 'r') record = list() for line in clip_file: if line.strip() == EOR: assert record[2] == '', "None-blank line expected separating the header from the body of the clippin:%s" % record[2] clip = dict() match = re.match( r'(.*?) \((.*)\)$', record[0] ) clip['title'], clip['author'] = match.groups() match = re.match( r'- (\w+) Loc. ([^|]+)\| Added on (\w+), (\w+ \d+, \d+), (\d+:\d+ \w\w)', record[1] ) clip['type'], clip['location'], clip['dow'], clip['date'], clip['time'] = match.groups() clip['content'] = "\n".join( record[3:] ) clip['title'] = clip['title'].strip() clip['author'] = clip['author'].strip() yield clip record = list() else: record.append( line.strip() ) clip_file.close() if __name__ == '__main__': from sys import argv outfile = 'output.txt' f = open(outfile, 'a') for n, r in enumerate( parse(argv[1]) ): f.write(r['content'] + '\n\n') f.write('--- ' + r['author'] + ', ' + r['title'] + ', ' + 'loc. ' + r['location']) f.write('\n\n-----\n\n') f.close()
Perl来解析Kindle Clippings perl
#!/usr/bin/perl -w use warnings; use strict; my $MY_CLIPPINGS_FILE = "test.txt"; my $OUTPUT_FILE = "output.txt"; # NOTE: the file is in UTF-8 format -- the first 3 bytes are # a byte order mark: EF BB BF = 0xFEFF when decoded via UTF-8 open my $clips_fh, "<:encoding(utf8)", $MY_CLIPPINGS_FILE or die "Unable to open file $MY_CLIPPINGS_FILE: $!"; # since there might be UTF-8 encoded characters in the input, also output UTF-8 open my $output_fh, ">:utf8", $OUTPUT_FILE # auto UTF-8 encoding on write or die "Unable to create output file $OUTPUT_FILE: $!"; binmode STDOUT, ":encoding(utf8)"; my %clips; while(<$clips_fh>) { my $title = $_; $title =~ s/^\x{FEFF}//; # remove BOM $title =~ s/\r\n/\n/g; my $line = <$clips_fh>; my ($type, $location); if($line =~ /^-\s+(\w+)\s+Loc.\s+(\d+)/) { ($type, $location) = ($1, $2); } else { $type = "bookmark" } if($type =~ /bookmark/i) { &skip_entry } else { while(1) { $line = <$clips_fh>; $line =~ s/\r\n/\n/g; next if $line =~ /^\s*$/; # skip blank lines last if $line =~ /^=======/; if($type =~ /note/i) { $clips{$title}{$location} .= '* ' .$line; } else { $clips{$title}{$location} .= '- ' .$line; } } } } foreach my $title (sort keys %clips) { print $output_fh "$title" . ('-' x (length($title) - 1)) . "\n"; foreach my $location (sort keys %{$clips{$title}}) { print $output_fh $clips{$title}{$location}; } print $output_fh "\n"; } exit; # ------------------------------------------ sub skip_entry { while(1) { my $line = <$clips_fh>; last if $line =~ /^=======/; } }
Elisp解析Kindle笔记 lisp
;;; repo: https://github.com/thamer/clip2org (defun clip2org-get-next-book-as-list () (let (title is-highlight header loc date page start end content) (setq start (point)) (if (not (re-search-forward "==========" nil t 1)) ;; Return nil nil (setq end (point)) (goto-char start) (setq title (buffer-substring-no-properties (line-beginning-position) (line-end-position))) ;; remove BOM (Byte-Order Marks) (setq title (replace-regexp-in-string "\u200f\\|\ufeff" "" title)) (when (re-search-forward "Highlight on" end t 1) (setq is-highlight t)) (beginning-of-line) (when (re-search-forward "- \\(.*\\)|" end t 1) (setq header (match-string 1))) (beginning-of-line) (when (re-search-forward "Page \\([0-9-]+\\)" end t 1) (setq page (match-string 1))) (when (re-search-forward "Location \\([0-9-]+\\)" end t 1) (setq loc (match-string 1))) (when (re-search-forward "Added on \\(.*\\)\n" end t 1) (setq date (match-string 1))) ;; From the end of date to ========== (if (re-search-forward "\n\\(.*?\\)\n==========" end t 1) (setq content (match-string 1))) (when (equal title "==========") (error "Clip2org: failed in getting content or quoted text.")) (forward-line) ;; Return list (list title is-highlight page loc date content header)))) (defun clip2org-convert-to-org (clist) "Process clip2org-alist and generate the output." ;; Process headers of each book (while (caar clist) (princ (format "\n* %s\n" (caar clist))) (let ((note-list (cdar clist))) ;; Process each clipping (while (car note-list) (let* ((item (car note-list)) (is-highlight (nth 0 item)) (page (nth 1 item)) (loc (nth 2 item)) (date (nth 3 item)) (content (nth 4 item))) (when is-highlight (princ (format "- %s\n" content)))) (setq note-list (cdr note-list)))) ;; Increment to the next book (setq clist (cdr clist)))) (defun clip2org-append-to-alist-key (key value alist) "Append a value to the key part of an alist. This function is used to create associated lists. If Key is not found, add new key to the list" (let ((templ) (results) (found)) (while alist ;; check if key is already in list (if (equal (caar alist) key) (progn (setq found t) (setq templ (list (nconc (car alist) (list value) templ))) ;; increment while loop (setq alist (cdr alist)) ;; add/create to a new list (setq results (append results templ))) (progn (setq results (append (list (car alist)) results)) (setq alist (cdr alist))))) ;; add the new key/value to old list (if (not (eq found t)) (setq results (append (list (list key value)) results))) results)) (save-excursion (find-file clipfile) (goto-char (point-min)) (let (clist (booklist (clip2org-get-next-book-as-list))) (while booklist (setq clist (clip2org-append-to-alist-key (car booklist) (cdr booklist) clist)) (setq booklist (clip2org-get-next-book-as-list))) (clip2org-convert-to-org clist)) (kill-this-buffer))
GPAC源码编译的brew公式 ruby
可以参考 这里 的教程,注意除了克隆 GPAC项目本身 外,还需要一个 gpac_extra_libs ,它的源码包可以从 这里 下载;或者可以直接 这里 下载已经编译好的版本,不管是自己编译还是直接用这些文件,总之最后需要把生成的文件都拷贝到 gpac/extra_lib
目录下。最后按照下面的Formula用brew安装即可: brew install ./gpac.rb
class Gpac < Formula desc "Multimedia framework for research and academic purposes" homepage "https://gpac.wp.mines-telecom.fr/" url "http://127.0.0.1:8000/gpac-0.6.2.tar.gz" sha256 "e5aa52e805a9ac56fdd2ea1f414b2fd49af5f3977b286f8737168e849587a131" head "https://github.com/gpac/gpac.git" depends_on "faad2" depends_on "sdl" depends_on "pkg-config" => :build depends_on :x11 => :optional depends_on "a52dec" => :optional depends_on "jpeg" => :optional depends_on "libogg" => :optional depends_on "libvorbis" => :optional depends_on "mad" => :optional depends_on "theora" => :optional depends_on "ffmpeg" => :optional def install args = ["--prefix=#{prefix}", "--mandir=#{man}"] system "./configure", *args system "make" system "make", "install" end test do system "#{bin}/MP4Box", "-add", test_fixtures("test.mp3"), "#{testpath}/out.mp4" File.exist? "#{testpath}/out.mp4" end end
Python moving average python
import numpy def smooth(x,window_len=11,window='hanning'): """smooth the data using a window with requested size. This method is based on the convolution of a scaled window with the signal. The signal is prepared by introducing reflected copies of the signal (with the window size) in both ends so that transient parts are minimized in the begining and end part of the output signal. input: x: the input signal window_len: the dimension of the smoothing window; should be an odd integer window: the type of window from 'flat', 'hanning', 'hamming', 'bartlett', 'blackman' flat window will produce a moving average smoothing. output: the smoothed signal example: t=linspace(-2,2,0.1) x=sin(t)+randn(len(t))*0.1 y=smooth(x) see also: numpy.hanning, numpy.hamming, numpy.bartlett, numpy.blackman, numpy.convolve scipy.signal.lfilter TODO: the window parameter could be the window itself if an array instead of a string NOTE: length(output) != length(input), to correct this: return y[(window_len/2-1):-(window_len/2)] instead of just y. """ if x.ndim != 1: raise ValueError, "smooth only accepts 1 dimension arrays." if x.size < window_len: raise ValueError, "Input vector needs to be bigger than window size." if window_len<3: return x if not window in ['flat', 'hanning', 'hamming', 'bartlett', 'blackman']: raise ValueError, "Window is on of 'flat', 'hanning', 'hamming', 'bartlett', 'blackman'" s=numpy.r_[x[window_len-1:0:-1],x,x[-1:-window_len:-1]] #print(len(s)) if window == 'flat': #moving average w=numpy.ones(window_len,'d') else: w=eval('numpy.'+window+'(window_len)') y=numpy.convolve(w/w.sum(),s,mode='valid') return y
Python插值 python
import numpy as np import matplotlib.pyplot as plt from scipy import interpolate x = np.arange(0, 10) y = np.exp(-x/3.0) plt.plot(x, y, 'ro') xnew = np.arange(0, 9, 0.1) # 'nearest', 'zero': 阶梯插值 # 'slinear': 线性插值 # 'quadratic': 2阶B样条插值 # 'cubic': 3阶B样条插值 for kind in ['nearest', 'zero', 'slinear', 'quadratic', 'cubic']: f = interpolate.interp1d(x, y, kind=kind) ynew = f(xnew) plt.plot(xnew, ynew, label=str(kind)) plt.legend(loc='higher right') plt.show()
检测突变值 python
"""Cumulative sum algorithm (CUSUM) to detect abrupt changes in data.""" from __future__ import division, print_function import numpy as np __author__ = 'Marcos Duarte, https://github.com/demotu/BMC' __version__ = "1.0.4" __license__ = "MIT" def detect_cusum(x, threshold=1, drift=0, ending=False, show=True, ax=None): """Cumulative sum algorithm (CUSUM) to detect abrupt changes in data. Parameters ---------- x : 1D array_like data. threshold : positive number, optional (default = 1) amplitude threshold for the change in the data. drift : positive number, optional (default = 0) drift term that prevents any change in the absence of change. ending : bool, optional (default = False) True (1) to estimate when the change ends; False (0) otherwise. show : bool, optional (default = True) True (1) plots data in matplotlib figure, False (0) don't plot. ax : a matplotlib.axes.Axes instance, optional (default = None). Returns ------- ta : 1D array_like [indi, indf], int alarm time (index of when the change was detected). tai : 1D array_like, int index of when the change started. taf : 1D array_like, int index of when the change ended (if `ending` is True). amp : 1D array_like, float amplitude of changes (if `ending` is True). Notes ----- Tuning of the CUSUM algorithm according to Gustafsson (2000)[1]_: Start with a very large `threshold`. Choose `drift` to one half of the expected change, or adjust `drift` such that `g` = 0 more than 50% of the time. Then set the `threshold` so the required number of false alarms (this can be done automatically) or delay for detection is obtained. If faster detection is sought, try to decrease `drift`. If fewer false alarms are wanted, try to increase `drift`. If there is a subset of the change times that does not make sense, try to increase `drift`. Note that by default repeated sequential changes, i.e., changes that have the same beginning (`tai`) are not deleted because the changes were detected by the alarm (`ta`) at different instants. This is how the classical CUSUM algorithm operates. If you want to delete the repeated sequential changes and keep only the beginning of the first sequential change, set the parameter `ending` to True. In this case, the index of the ending of the change (`taf`) and the amplitude of the change (or of the total amplitude for a repeated sequential change) are calculated and only the first change of the repeated sequential changes is kept. In this case, it is likely that `ta`, `tai`, and `taf` will have less values than when `ending` was set to False. See this IPython Notebook [2]_. References ---------- .. [1] Gustafsson (2000) Adaptive Filtering and Change Detection. .. [2] hhttp://nbviewer.ipython.org/github/demotu/BMC/blob/master/notebooks/DetectCUSUM.ipynb Examples -------- >>> from detect_cusum import detect_cusum >>> x = np.random.randn(300)/5 >>> x[100:200] += np.arange(0, 4, 4/100) >>> ta, tai, taf, amp = detect_cusum(x, 2, .02, True, True) >>> x = np.random.randn(300) >>> x[100:200] += 6 >>> detect_cusum(x, 4, 1.5, True, True) >>> x = 2*np.sin(2*np.pi*np.arange(0, 3, .01)) >>> ta, tai, taf, amp = detect_cusum(x, 1, .05, True, True) """ x = np.atleast_1d(x).astype('float64') gp, gn = np.zeros(x.size), np.zeros(x.size) ta, tai, taf = np.array([[], [], []], dtype=int) tap, tan = 0, 0 amp = np.array([]) # Find changes (online form) for i in range(1, x.size): s = x[i] - x[i-1] gp[i] = gp[i-1] + s - drift # cumulative sum for + change gn[i] = gn[i-1] - s - drift # cumulative sum for - change if gp[i] < 0: gp[i], tap = 0, i if gn[i] < 0: gn[i], tan = 0, i if gp[i] > threshold or gn[i] > threshold: # change detected! ta = np.append(ta, i) # alarm index tai = np.append(tai, tap if gp[i] > threshold else tan) # start gp[i], gn[i] = 0, 0 # reset alarm # THE CLASSICAL CUSUM ALGORITHM ENDS HERE # Estimation of when the change ends (offline form) if tai.size and ending: _, tai2, _, _ = detect_cusum(x[::-1], threshold, drift, show=False) taf = x.size - tai2[::-1] - 1 # Eliminate repeated changes, changes that have the same beginning tai, ind = np.unique(tai, return_index=True) ta = ta[ind] # taf = np.unique(taf, return_index=False) # corect later if tai.size != taf.size: if tai.size < taf.size: taf = taf[[np.argmax(taf >= i) for i in ta]] else: ind = [np.argmax(i >= ta[::-1])-1 for i in taf] ta = ta[ind] tai = tai[ind] # Delete intercalated changes (the ending of the change is after # the beginning of the next change) ind = taf[:-1] - tai[1:] > 0 if ind.any(): ta = ta[~np.append(False, ind)] tai = tai[~np.append(False, ind)] taf = taf[~np.append(ind, False)] # Amplitude of changes amp = x[taf] - x[tai] if show: _plot(x, threshold, drift, ending, ax, ta, tai, taf, gp, gn) return ta, tai, taf, amp def _plot(x, threshold, drift, ending, ax, ta, tai, taf, gp, gn): """Plot results of the detect_cusum function, see its help.""" try: import matplotlib.pyplot as plt except ImportError: print('matplotlib is not available.') else: if ax is None: _, (ax1, ax2) = plt.subplots(2, 1, figsize=(8, 6)) t = range(x.size) ax1.plot(t, x, 'b-', lw=2) if len(ta): ax1.plot(tai, x[tai], '>', mfc='g', mec='g', ms=10, label='Start') if ending: ax1.plot(taf, x[taf], '<', mfc='g', mec='g', ms=10, label='Ending') ax1.plot(ta, x[ta], 'o', mfc='r', mec='r', mew=1, ms=5, label='Alarm') ax1.legend(loc='best', framealpha=.5, numpoints=1) ax1.set_xlim(-.01*x.size, x.size*1.01-1) ax1.set_xlabel('Data #', fontsize=14) ax1.set_ylabel('Amplitude', fontsize=14) ymin, ymax = x[np.isfinite(x)].min(), x[np.isfinite(x)].max() yrange = ymax - ymin if ymax > ymin else 1 ax1.set_ylim(ymin - 0.1*yrange, ymax + 0.1*yrange) ax1.set_title('Time series and detected changes ' + '(threshold= %.3g, drift= %.3g): N changes = %d' % (threshold, drift, len(tai))) ax2.plot(t, gp, 'y-', label='+') ax2.plot(t, gn, 'm-', label='-') ax2.set_xlim(-.01*x.size, x.size*1.01-1) ax2.set_xlabel('Data #', fontsize=14) ax2.set_ylim(-0.01*threshold, 1.1*threshold) ax2.axhline(threshold, color='r') ax1.set_ylabel('Amplitude', fontsize=14) ax2.set_title('Time series of the cumulative sums of ' + 'positive and negative changes') ax2.legend(loc='best', framealpha=.5, numpoints=1) plt.tight_layout() plt.show()
简单的Markdown页面样式 markdown
html { margin: 0 1em; } body { margin: 0 auto; word-wrap: break-word; max-width: 700px; font-size: 110%; line-height: 1.5; } /* image */ figure { text-align: center; } img { max-width: 85%; } /* code */ pre { overflow-x: auto; word-wrap: normal; background-color: #f9f9f9; padding: 0.8em; } /* blockquote */ blockquote { color: #777; font-style: italic; padding-left: 0.8em; border-left: 0.3em solid #ccc; } /* table */ table, th, td { margin: 0px auto; border: 1px solid grey; } th, td { padding: 0.3em; }
Python来格式化输出json文件 python json
"""Command-line tool to validate and pretty-print JSON Usage:: $ echo '{"json":"obj"}' | python -m json.tool { "json": "obj" } $ echo '{ 1.2:3.4}' | python -m json.tool Expecting property name enclosed in double quotes: line 1 column 3 (char 2) """ import argparse import collections import json import sys def main(): prog = 'python -m json.tool' description = ('A simple command line interface for json module ' 'to validate and pretty-print JSON objects.') parser = argparse.ArgumentParser(prog=prog, description=description) parser.add_argument('infile', nargs='?', type=argparse.FileType(), help='a JSON file to be validated or pretty-printed') parser.add_argument('outfile', nargs='?', type=argparse.FileType('w'), help='write the output of infile to outfile') parser.add_argument('--sort-keys', action='store_true', default=False, help='sort the output of dictionaries alphabetically by key') options = parser.parse_args() infile = options.infile or sys.stdin outfile = options.outfile or sys.stdout sort_keys = options.sort_keys with infile: try: if sort_keys: obj = json.load(infile) else: obj = json.load(infile, object_pairs_hook=collections.OrderedDict) except ValueError as e: raise SystemExit(e) with outfile: json.dump(obj, outfile, sort_keys=sort_keys, indent=4, ensure_ascii=False) outfile.write('\n') if __name__ == '__main__': main()
Emacs-lisp解析csv的一个例子
id,game,url,rating,category,release_date,platforms,genres,themes,companies,description 1107,Metroid: Zero Mission,https://www.igdb.com/g/ur,8.62793915424818,Main Game,"[""2015-Mar-12 (Australia [AU])"", ""2015-Mar-12 (Europe [EU])"", ""2016-Jan-14 (North America [NA])"", ""2014-Jun-19 (Japan [JP])"", ""2004-Mar-19 (Australia [AU])"", ""2004-Feb-09 (North America [NA])"", ""2004-Apr-08 (Europe [EU])"", ""2004-May-27 (Japan [JP])""]","[""Game Boy Advance"", ""Wii U""]","[""Adventure"", ""Platform"", ""Shooter""]","[""Action"", ""Science fiction""]","[""Nintendo Research & Development 1"", ""Nintendo""]", 7346,The Legend of Zelda: Breath of the Wild,https://www.igdb.com/g/5o2,9.26063084572708,Main Game,"[""2017-Mar-03 (Worldwide [WW])"", ""2017-Mar-03 (Worldwide [WW])""]","[""Nintendo Switch"", ""Wii U""]","[""Adventure"", ""Role-playing (RPG)"", ""Sport""]","[""Action"", ""Fantasy"", ""Open world""]","[""Nintendo EPD"", ""Nintendo"", ""Nintendo of America"", ""Nintendo of Europe""]", 1041,The Legend of Zelda: Oracle of Ages,https://www.igdb.com/g/sx,8.03766831129613,Main Game,"[""2013-May-30 (Australia [AU])"", ""2013-May-30 (Europe [EU])"", ""2013-May-30 (North America [NA])"", ""2013-Feb-27 (Japan [JP])"", ""2001-Oct-05 (Europe [EU])"", ""2001-May-14 (North America [NA])"", ""2001-Feb-27 (Japan [JP])""]","[""Game Boy Color"", ""Nintendo 3DS""]","[""Adventure"", ""Role-playing (RPG)""]","[""Action""]","[""Capcom"", ""Nintendo""]",
(defun parse-csv-string-rows (data separator quote-char line-sep) "Parse a separated and quoted string DATA into a list of list of strings. Uses SEPARATOR as the column seperator, QUOTE-CHAR as the string quoting character, and LINE-SEP as the line separator." (let ((items '()) (lines '()) (offset 0) (rawlines (if line-sep (split-string data line-sep) (list data))) (line "") (current-word "") (state :read-word)) (catch 'return (progn (setq line (pop rawlines)) (cl-loop (when (or (not line) (= offset (length line))) ;; all done (cl-ecase state (:in-string (if rawlines; have more lines (progn (setq offset 0) (setq current-word (concat current-word line-sep)) (setq line (pop rawlines))) (error "Unterminated string"))) (:read-word ;; new line! (push (nreverse (cons current-word items)) lines) (if rawlines (progn (setq current-word "") (setq items '()) (setq offset 0) (setq line (pop rawlines))) (throw 'return (nreverse lines)))))) ;; handle empty line (if (= 0 (length line)) (cl-ecase state (:in-string (setq offset 0) (setq current-word (concat current-word line-sep)) (setq line (pop rawlines))) (:read-word ;; new line! (push (nreverse (cons current-word items)) lines) (setq offset 0) (setq line (pop rawlines)))) (let ((current (aref line offset))) (cond ((char-equal separator current) (cl-ecase state (:in-string (setq current-word (concat current-word (char-to-string current)))) (:read-word (push current-word items) (setq current-word "")))) ((char-equal quote-char current) (cl-ecase state (:in-string (let ((offset+1 (1+ offset))) (cond ((and (/= offset+1 (length line)) (char-equal quote-char (aref line offset+1))) (setq current-word (concat current-word (char-to-string quote-char))) (cl-incf offset)) (t (setq state :read-word))))) (:read-word (setq state :in-string)))) (t (setq current-word (concat current-word (char-to-string current)))))) (cl-incf offset))))))) (with-temp-buffer (princ "<table>\n<thead><tr><th>Title</th><th>ID</th></tr></thead>\n") (insert-file-contents csvfile) (let ((csvlines (cdr (split-string (buffer-string) "\n" t)))) (dolist (csvline csvlines) (let* ((csvcols (car (parse-csv-string-rows csvline ?\, ?\" nil))) (game-id (nth 0 csvcols)) (game-name (nth 1 csvcols)) (game-url (nth 2 csvcols))) (princ (format "<tr><td>%s</td><td><a href=\"%s\">%s</a></td></tr>\n" game-name game-url game-id))))) (princ "</tbody></table>"))
Import to Jumsoft Money from MoneyWiz
import pandas as pd mw = pd.read_csv("moneywiz.csv") jumsoft = pd.DataFrame(columns=["Date", "Payee", "Category", "Amount", "Balance", "Type", "Account", "Tags", "Notes", "Currency", "Currency Rate"]) def conv_date(date): dl = date.split("/") m = dl[0][1:] if dl[0][0] == '0' else dl[0] d = dl[1][1:] if dl[1][0] == '0' else dl[1] return m + "/" + d + "/" + dl[2][2:] for i, row in mw.iterrows(): mdict = {} if not pd.isnull(row['Name']): continue isexpense = True if row['Amount'][0] == '-' else False mdict['Date'] = conv_date(row['Date']) mdict['Payee'] = row['Payee'] if not pd.isnull(row['Transfers']): mdict['Category'] = "Transfers to:" + row['Transfers'] if isexpense else "Transfers from:" + row['Transfers'] else: mdict['Category'] = row['Category'] mdict['Amount'] = row['Amount'].replace(",", "") mdict['Balance'] = row['Balance'].replace(",", "") mdict['Type'] = "Expense" if isexpense else "Income" mdict['Account'] = row['Account'] mdict['Tags'] = row['Tags'] mdict['Notes'] = row['Description'] mdict['Currency'] = row['Currency'] mdict['Currency Rate'] = "1" # Tranfers jumsoft = jumsoft.append(mdict, ignore_index=True) jumsoft.to_csv("/Users/jiaxi/Desktop/j.csv", index=False)