Pythonでテキストファイルから数字を読み込む際のエラー

このQ&Aのポイント
  • Pythonでテキストファイルから数字を読み込む際に発生するエラーについて質問します。
  • スペースで区切られたデータをパラメータセットとして配列に格納しようとしていますが、エラーが出てしまいます。
  • エラーメッセージは「TypeError: argument 2 to map() must support iteration」です。
回答を見る
  • ベストアンサー

Python: TypeError

Pythonでテキストファイルから数字を読み込む時に、スペースで区切られたデータをパラメータセットとして配列の中に格納したいのですが、その際にチェック事項があってFor LoopにTryを挟んでいます。この状態でどうしても下記のエラーが出るのですが、どのようにすれば良いのでしょうか? 宜しくお願い致します。 TypeError: argument 2 to map() must support iteration --- def ReadOutput1(): f = open('C:/Users/.../output1.txt','rb') output = [] for line in f: ls = line.split(' ') for i in range(4, 8)): try: modelParams[i-4] = map(add, float(ls[i])) except ValueError: (...) return output

質問者が選んだベストアンサー

  • ベストアンサー
  • siffon9
  • ベストアンサー率64% (136/211)
回答No.2

こんにちは mapの第二引数にイテレータ型を要するということなので、lsの必要な部分[4:8]を数値化したリスト(ls_f)を作成して、それをmapの第二引数に与えてあげれば良いのではないでしょか? def add(x): return(x + 1.0) line = "0.0 1.0 2.0 3.0 4.0 5.0 6.0 7.0e-12 8.0 9.0" ls = line.split() ls_f = list(map(float, ls[4:8])) # lsの必要な部分のみ数値化 print(list(ls_f)) # => [4.0, 5.0, 6.0, 7e-12] modelParams = list(map(add, ls_f)) print(modelParams) # => [5.0, 6.0, 7.0, 1.000000000007] ※私の環境python3.4.2ではmapがリストを返さなかったので明示してリストにしています。 ※よくわかりませんが、私の環境では、指数表示の数値文字をfloatに与えてもエラーになりませんでした、  指数表示数値を別処理する必要があるのであれば、その関数をfloatの代わりに作成する必要があると思います。

codingbeginner
質問者

お礼

ありがとうございます。 おそらくmapの使い方が間違っていたようでした。 >map(float, ls[4:8]) の使い方を知らず、 >float(map(add, ls[i])) という形でやっていて失敗していたようです。 上記方法で上手く実行できました。ありがとうございます。

codingbeginner
質問者

補足

私の使っているPython2.7では「テキストファイルからの読み込み」はエラーになります。現在2の方で慣れているので慣れているので、他に色々と不便を感じたら乗り換えたいと思います。 別処理は既に用意しています。最初のコードを書く段階でそこまで書くのは焦点が分散するかなと思いまして。

その他の回答 (2)

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.3

そうなると、単純に modelParams[i-4] = add(float(ls[i])) なだけで、わざわざmapを使う必要はありません。 > 科学数値表示(例1.2345e-12)になっているものを例外処理を行い これは、どういう例外処理でしょうか? ・ 1.2345e-12は「(おそらく誤差からくる)非常に小さい数値」なので 0 として扱う → 0.0000000000012345 と書いても同じ数値ですが、どう扱いますか? ・ 12.3はそのまま使う → 1.23e+1 と書いても同じ数値ですが、どう扱いますか? 指数表現の文字列でも、floatで数値に変換できます。 http://docs.python.jp/2/library/functions.html#float 2.xのマニュアルでは「引数が文字列の場合、十進の数または浮動小数点数を含んでいなければなりません」とちょっと曖昧な表現ですが http://docs.python.jp/3.3/library/functions.html#float 3.xでは、「浮動小数点数リテラルで表記」と明記されています。 全て単純にfloatで変換→数値で判断して例外処理 というのがスマートだと思います。 スライスを使うと、リストの一部分をまとめて変更することができます modelParams[0:4]=(1,2,3,4) # modelParams[0] =1, modelParams[1]=2 , ... なので、forのところは modelParams[0:4]=map(add,map(float,ls[4:8] )) と書くこともできます。 mapの戻り値は、Python2からPython3になったときに、リストからイテレータへ変更されています。 http://docs.python.jp/3.3/whatsnew/3.0.html#views-and-iterators-instead-of-lists > いくつかの良く使われているAPIはもはやリストを返しません: > map() and filter() return iterators. 他にも、2→3で大きく変更されています。 今回のTypeErrorは、(メッセージが若干違うものの)2,3共通なので問題ありません。 ですが、「Python2用のスクリプトをPython3で使おうとしてうまく動かない(あるいは、その逆)」ということがよくあります。 質問の際には、使用しているPyhtonのバージョンを明記するようにしましょう。

codingbeginner
質問者

お礼

ご回答ありがとうございます。 仰るとおりmap(float,ls[4:8] )で正常に動作しました。 科学数値表記とは使わないのですね?英語ではScientific Numberですので、日本語で直訳でいけるかと思いましたが失礼致しました。スライスの場合はそれぞれに数値化の処理を適用させなければならないので、後者のみ試しました。 以後はバージョンも明記するよう心がけます。

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.1

http://docs.python.jp/2/library/functions.html#map mapは map(関数, イテレータ型) とすると [ 関数(イテレータの0番目),関数(イテレータの1番目),関数(イテレータの2番目), ...] というリストを返す関数です。 http://docs.python.jp/2/library/stdtypes.html#typeiter map(add, float(ls[i])) だと、floatは実数を返す関数であり、実数はイテレータ型ではありません。 よってエラーになります TypeError: argument 2 to map() must support iteration 型のエラー: map()の 引数2 はイテレーションに対応していなければならない と、エラーメッセージに書いてある通りです。 modelParams[i-4] = map(add, float(ls[i])) は何がやりたいのでしょうか? mapはリストを返します。  modelParams[i-4] に入れたいのは、リストですか?( modelParams[i-4] = [1,2] みたいに )  別の数値かなにかですか?( modelParams[i-4] = 3.5 みたいに )

codingbeginner
質問者

補足

ご回答ありがとうございます。そういうことでしたか。 ここでやりたかったのは、一度計算処理してoutput1.txtに出力したデータを再度読み込む際に、5番目のデータからある個数だけをmodelParamsに収納したかったのです。その際、科学数値表示(例1.2345e-12)になっているものを例外処理を行い、それ以外は単純にfloatで数値として認識させる作業を行っております。 txtにしなければ数値として通常認識するのですが(csvなどでも数値になりますが、ファイルを開いた時に、データセットで[]で括られたもの(scipy.optimize.minimizeでの戻り値など)にカンマを打てなかったり、スペース区切りにすると'['や']'にもそれぞれセル一つ分使ったりなので)、txtを使う方法で考えています。 少々複雑になりましたが、要は2段落目に示した通りで、3段落目は補足です。 >modelParams[i-4] に入れたいのは、リストですか? ということで、この問いには数値になります。例:modelParams=[3 1 4 1 5 ...] 宜しくお願い致します。

関連するQ&A

  • Pythonプログラミングでエラー

    Pythonのプログラムを教科書をみながら勉強しはじめました。 バージョンは3.0.1です。 下記の初歩的なプログラムで#の行でエラーがでて対応方法が わかりません。 アドバイスいただけませんでしょうか。 #! /python30/python # coding:shift_jis ''' 簡単な電卓です。 Usage: mycalc.py n (+-*/) m ''' import sys, operator OP={'+':operator.__add__,\ '-':operator.__sub__,\ '*':operator.__mul__,\ '/':operator.__truediv__,\ } def calc(ls): assert len(ls)==3 #ここでエラー try: op=OP(ls.pop(1)) # 真ん中の文字列をpop,数字のみ残る。 x,y=[float(u) for u in ls] # 残った文字列をfloatに変換 except: print('Err:数字 演算子(+-*/) 数字 の順に引数をセットしてください。') sys.exit() return op(x,y) if __name__=='__main__': print(calc(sys.argv[1:])) #ここでエラー (ここで質問するとTABのインデントがなくなってしまうようです。)

  • プログラミング(Python)について

    「整数 a_1, a_2, a_3, a_4, a_5 が半角スペース区切りで与えられるので、改行区切りにして 5 行で出力してください。」というPythonの問題です。なぜmapを用いた場合は、for i in range(1000)ではなくて、for a_i in aにしなければならないのか分かりません。 そもそもa_iの意味も分かりません... 調べてもよく分かりませんでした。

  • python超初心者です(3時間目)。pythonで以下のようなランダ

    python超初心者です(3時間目)。pythonで以下のようなランダム数列を生成させるにはどうしたらいいのでしょうか? 最終結果のイメージ(16進数8桁の数列x20行): 0 : c39a29eb 1 : b26cc9bb 2 : 4c494e47 ... 19: 93c85836 以下のようにコードを組んでみたのですが、 > tmp = ws.join(list) > TypeError: sequence item 0: expected string, int found のようなエラーが出てしまいます。どうやら数字を連結しようとしてるのでダメなのかな?と思っています。 ======================================== #! /usr/bin/python import random list = [] ws = "" for i in range (20): print i, ":", for j in range(8): list.append(random.randint(0,15)) tmp = ws.join(list) print tmp list = [] tmp = "" ======================================== ※ printでは必ずスペースが入ってしまうので、それを嫌う場合配列に入れて、要素を連結させなくてはならない、とwebにあったので、その方向で試してみました。 ※ また、ここではあくまでrandom を使用し、一文字(0,1,2,...E,F)づつ出力させたいと思っています。 なお、perlでは以下のように書くことができたのですが... ======================================== #! /usr/bin/perl for($i=0; $i<20; $i++){ printf ("%-02s: ", $i); for($j=0; $j<8; $j++){ printf("%x", int(rand(15)) ); } print "\n"; } ======================================== ※ んー第二言語としてpythonを学習してみていますが道のり険しそうです(やっぱrubyにしようか)... 宜しくお願い致します。

  • pythonでバイナリデータを配列に読み込みたい

    python初心者なので、できるだけお手柔らかにお願いします。 pythonのバージョンは2.7.3です。 ===================================================== あるバイナリデータ(test.bin)から、 2バイトずつ100*100の2次元配列に読み込ませたいのですが、 配列への読み込ませ方が分からず悩んでいます。 ===================================================== #### ここから sampleスクリプト(未完) ################ f = open("./test.bin", "rb") x = 100 y = 100 bytesize = 2 data = f.read(bytesize*x*y) array = [[0 for j in range(x)] for i in range(y)] ############################################## 上記の後、arrayの各要素に2byteずつ整数値としてデータを読み込ませたいのですが、 dataからarrayへの受け渡し方法が分からず悩んでいます。 かなり初歩的な質問かも知れませんが、ヒントでもいいので教えて下さい。 また、上記の時点で誤っていることがありましたら ご教授お願いします。

  • python

    pythonについての質問です。 def S_sa(k=1) for step in xrange(k) : if step == 0 : print 'a' else print 'b' というコードがあって、なぜかprint aが実行されるのはなぜでしょうか? xrangeのreturnは1ではないのでしょうか?

  • python3

    def walk(): for i in range(hor): if i == hor_now: print("*", end="") for h in range(var - 1): print("〇",end ="") print() else: for h in range(var): print("〇",end ="") print() print(walk) 普通に出力することはできるんですが、defでユーザー定義関数にすると<function walk at 0x000001541505B9D0>こうなってしまいます、なぜでしょうか?

  • Python in演算子について

    Pythonにin演算子があります。 これは、真偽値をとるため、if文等でつかわれています。 しかし、for文のin for i in a: aはオブジェクトでiはその要素ですが、この場合は真偽値をとりません。 この場合はin演算子としてのinとは考えないのが普通のような気がするのですが? 宜しくねがいます。

  • パソコンを変えるとpythonを使えなくなった

    スクリプトにimportしているものはtweepyのみです。 tweepyもpythonも最新のものをインストール済みです。 同じフォルダにある別の簡単なスクリプトは正常に動作しました。 PyScripterを使った時のエラーメッセージは以下のものとなります。 どうすれば改善されるか教えていただけないでしょうか。 Traceback (most recent call last): File "C:\Users\user7\Desktop\TC.py", line 19, in <module> tweets = api.user_timeline(Account, count=200, page=1, tweet_mode = 'extended') File "C:\Users\user7\AppData\Local\Programs\Python\Python310\lib\site-packages\tweepy\api.py", line 33, in wrapper return method(*args, **kwargs) File "C:\Users\user7\AppData\Local\Programs\Python\Python310\lib\site-packages\tweepy\api.py", line 46, in wrapper return method(*args, **kwargs) TypeError: API.user_timeline() takes 1 positional argument but 2 were given

  • csvファイルでpythonを扱いたいんですが

    以下のようなcsvファイルを使って shop,ymd,gend,age,area,amt 20,2008-05-01,3,5,014,128 22,2008-05-01,2,4,015,350 : 二列目の日別、つまりymd別に最後列のamdの小計を出したいんですが、なかなか出てくれません。以下のようなプログラムを組んだんですが #!/usr/bin/env python import csv def readcsv(filename):  L = [line[:-1] for line in file(filename).readlines()]  return map((lambda s: s.split(',')),L) csvlist = readcsv('/data/testdata/journal/j080240.csv') i=0 for line in csvlist[1:]: buydict = dict(zip(csvlist[0],line)) if buydict.itervalues('ymd'): i+=int(buydict['amt']) else: print '%s,%d'% buydict['ymd'],i i=0 とこのように書きました。もう行き詰ってきたので、質問させてもらいました。誰かご教授願えますか?

  • Python勉強中の初心者です。

    只今、Pythonを勉強中です。オライリーの”初めてのPython”で勉強中なのですが途中で分からないところがあったので質問させてください。 >>>def min1 (*args): res = args[0] for arg in args[1:]: if arg < res: res = arg return res >>>print min1(3,4,1,2) 1 という参考が有り考えてたら訳が解らなくなってしまいツマづいていますでどういう流れで1になるのかわかる方アドバイスください。

専門家に質問してみよう