77420


形が整っていないcsvから特定の値を取り出したい。（行と列を指定して）  
以下のようなcsvがあり、pandasを用いてデータを取り出そうとするとエラーが当然出てきます。

実現したいことは、

  * 4行3列の値を取り出す
  * 17行3列の値を取り出す

のような操作をできるようにしたいのです。

**対象のCSV:**

[code]

    SetupTitle, 0_NMOS_id-vg_vg-0.5-1_step2m_vd0.1_vb0-1_vsub0
    PrimitiveTest, I/V Sweep
    TestParameter, Context.MainFrame, B1500A
    TestParameter, Channel.UnitType, SMU, SMU, SMU, SMU, SMU
    TestParameter, Channel.Unit, SMU1:HR, SMU2:MP, SMU3:MP, SMU4:MP, SMU5:MP
    TestParameter, Channel.IName, ID, IG, IS, IB, Isub
    TestParameter, Channel.VName, VD, VG, VS, VB, Vsub
    TestParameter, Channel.Mode, V, V, V, V, V
    TestParameter, Channel.Func, CONST, VAR1, CONST, VAR2, CONST
    TestParameter, Channel.Index, 
    
[/code]

追記

ご回答頂いたことを基に、プログラムを実行させて頂きましたが、  
エラーが出力され、うまく動かせません。  
また、元のcsvには、1行目は空欄となっています。  
空欄はミスではなく空欄があることが正しいです。

実行コード

[code]

    df = pd.read_csv(file_names, names=list("abcdefg))
    
[/code]

エラー

[code]

    ---------------------------------------------------------------------------
    ValueError                                Traceback (most recent call last)
    <ipython-input-14-c9fb50f13326> in <module>
          1 # df = pd.read_csv(file_names, skiprows=18,names=list["asdfghj"])
    ----> 2 df = pd.read_csv(file_names, names=list("abcdefg"))
          3 
          4 # df = df.drop('DataName', axis=1)
    
    ~/.local/lib/python3.6/site-packages/pandas/io/parsers.py in read_csv(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, squeeze, prefix, mangle_dupe_cols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, skipfooter, nrows, na_values, keep_default_na, na_filter, verbose, skip_blank_lines, parse_dates, infer_datetime_format, keep_date_col, date_parser, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, dialect, error_bad_lines, warn_bad_lines, delim_whitespace, low_memory, memory_map, float_precision)
        686     )
        687 
    --> 688     return _read(filepath_or_buffer, kwds)
        689 
        690 
    
    ~/.local/lib/python3.6/site-packages/pandas/io/parsers.py in _read(filepath_or_buffer, kwds)
        435     # See https://github.com/python/mypy/issues/1297
        436     fp_or_buf, _, compression, should_close = get_filepath_or_buffer(
    --> 437         filepath_or_buffer, encoding, compression
        438     )
        439     kwds["compression"] = compression
    
    ~/.local/lib/python3.6/site-packages/pandas/io/common.py in get_filepath_or_buffer(filepath_or_buffer, encoding, compression, mode, storage_options)
        241     if not is_file_like(filepath_or_buffer):
        242         msg = f"Invalid file path or buffer object type: {type(filepath_or_buffer)}"
    --> 243         raise ValueError(msg)
        244 
        245     return filepath_or_buffer, None, compression, False
    
    ValueError: Invalid file path or buffer object type: <class 'list'>
    
[/code]


CC BY-SA 4.0
2021-06-09T04:12:17.947
77418
2021-06-09T13:41:53.460
2021-06-09T11:43:47.167
3060
42741
question
python pandas csv
行ごとに列の数が異なる CSV から、特定の値を取り出したい


csvの情報をいったん行データとして読み込み、それをカンマ区切りで分割する方法でも対応可能です。  
[SO本家の類似質問](https://stackoverflow.com/q/55188544)

[code]

    import pandas as pd
    df = pd.read_csv('data.csv', header=None, sep='\n')
    df = df[0].str.split(',', expand=True)
    # 4行3列の値を取り出す
    value = df.iloc[3][2]
    print(value) # "SMU"が返る
    
[/code]


CC BY-SA 4.0
2021-06-09T04:38:48.173
77419
2021-06-09T04:38:48.173
9820
77418
answer


こちらの記事の回答を応用すれば、CSVデータ内容に応じたDataFrameを取得出来るでしょう。  
[Pandas read_csv expects wrong number of columns, with ragged csv file
の回答](https://stackoverflow.com/a/41734794/9014308)

ヘッダー行の有無とかを調整するなら、それに応じた処理を追加する必要がありますが。  
こんな感じになります。

[code]

    import pandas as pd
    
    def ragged_csv(filename):
        f=open(filename)
        max_n=0
        for line in f.readlines():
            words = len(line.split(','))  #### 区切り文字は , に戻す
            if words > max_n:
                max_n=words
        lines=pd.read_csv(filename,sep=',',names=range(max_n))  #### 上記に同じ
        return lines
    
    df = ragged_csv('data.csv')
    df.fillna('', inplace=True) #### 必要ならば、存在しなかったデータ(NaN)を空文字列に変更
    
[/code]

出来たDataFrameからは、@payaneco さん回答のようにデータを取得出来るでしょう。

* * *

その後、`csv`モジュールで読み込んでからpandasでDataFrameにすれば同様のことが少し簡単に出来るのを見つけました。色々組み合わせて約2行で出来ますね。  
[csv.reader(csvfile, dialect='excel',
**fmtparams)](https://docs.python.org/ja/3/library/csv.html#csv.reader)  
[PythonでCSVファイルを読み込み・書き込み（入力・出力）](https://note.nkmk.me/python-csv-reader-
writer/)  
[Convert jagged array to Pandas
dataframe](https://stackoverflow.com/q/63496104/9014308)

[code]

    import csv
    import pandas as pd
    
    with open('data.csv', newline='') as f:
        df = pd.DataFrame([row for row in csv.reader(f, skipinitialspace=True)]).dropna(how='all').reset_index(drop=True).fillna('')
    
[/code]

  * `, ID, IG, IS, IB, Isub`とかのカンマ後の空白1文字を無効にするなら、`, skipinitialspace=True`を残し、有効にするなら削る。

  * CSVファイル内で1行まるまるデータが無い部分を削除するなら、`.dropna(how='all').reset_index(drop=True)`を残し、有効にするなら削る。

  * CSVファイルで行内にデータが無い部分の値を空文字列にするなら`.fillna('')`を残し、`None`のままで良いなら`.fillna('')`を削り、何か別の値にしたいなら`.fillna('')`の`()`内に指定する。


CC BY-SA 4.0
2021-06-09T04:41:36.710
77420
2021-06-09T11:17:18.197
2021-06-09T11:17:18.197
26370
26370
77418
answer


事前にカラム数の最大値を取得しておく方法も考えられます。

[code]

    import pandas as pd
    import csv
    
    with open('data.csv') as f:
      ncol = max(len(r) for r in csv.reader(f))
      f.seek(0)
      df = pd.read_csv(
             f, names=range(ncol), header=None, na_filter=False,
             converters={c: str.strip for c in range(ncol)},
             skip_blank_lines=False)
    
    print(df)
    print(f'4行3列の値 = {df.iloc[3, 2]}')
    
    # 出力結果(入力したCSVファイルの1行目は空行)
                    0                                               1  ...        5        6
    0                                                                  ...                  
    1      SetupTitle  0_NMOS_id-vg_vg-0.5-1_step2m_vd0.1_vb0-1_vsub0  ...                  
    2   PrimitiveTest                                       I/V Sweep  ...                  
    3   TestParameter                               Context.MainFrame  ...                  
    4   TestParameter                                Channel.UnitType  ...      SMU      SMU
    5   TestParameter                                    Channel.Unit  ...  SMU4:MP  SMU5:MP
    6   TestParameter                                   Channel.IName  ...       IB     Isub
    7   TestParameter                                   Channel.VName  ...       VB     Vsub
    8   TestParameter                                    Channel.Mode  ...        V        V
    9   TestParameter                                    Channel.Func  ...     VAR2    CONST
    10  TestParameter                                   Channel.Index  ...                  
    
    [11 rows x 7 columns]
    4行3列の値 = B1500A
    
[/code]

`pandas.read_csv()` で `na_filter=False` を指定すると欠損カラムには空文字列(`''`)が挿入されます。


CC BY-SA 4.0
2021-06-09T06:07:05.813
77422
2021-06-09T13:41:53.460
2021-06-09T13:41:53.460
77418
answer