リストからデータフレームに列を追加します


94

次のような列を持つデータフレームがあります。

A   B   C  
0   
4
5
6
7
7
6
5

Aの値の可能な範囲は、0から7までです

また、私はこのような8つの要素のリストを持っています:

List=[2,5,6,8,12,16,26,32]  //There are only 8 elements in this list

列Aの要素がnの場合、リストのn番目の要素を新しい列(「D」など)に挿入する必要があります。

データフレーム全体をループせずに、これを一度に行うにはどうすればよいですか?

結果のデータフレームは次のようになります。

A   B   C   D
0           2
4           12
5           16
6           26
7           32
7           32
6           26
5           16

注:データフレームは巨大であり、反復は最後のオプションオプションです。ただし、必要に応じて、「リスト」の要素をdictなどの他のデータ構造に配置することもできます。


1
(小さい)おもちゃの例が必要で、望ましい結果が得られると思います。少し漠然とした雰囲気に聞こえます。
Andy Hayden

11
変数を「リスト」と呼ぶことは絶対にしないでください。任意の言語で。
lucid_dreamer

回答:


50

IIUC、(残念ながら名前が付けられた)Listをにするとndarray、自然にインデックスを付けることができます。

>>> import numpy as np
>>> m = np.arange(16)*10
>>> m[df.A]
array([  0,  40,  50,  60, 150, 150, 140, 130])
>>> df["D"] = m[df.A]
>>> df
    A   B   C    D
0   0 NaN NaN    0
1   4 NaN NaN   40
2   5 NaN NaN   50
3   6 NaN NaN   60
4  15 NaN NaN  150
5  15 NaN NaN  150
6  14 NaN NaN  140
7  13 NaN NaN  130

ここで新しいmを作成しましたが、を使用するm = np.asarray(List)と、同じことが機能するはずです。の値はdf.A、の適切な要素を選択しmます。


古いバージョンのnumpyを使用m[df.A.values]している場合numpyは、代わりに使用する必要がある場合があることに注意してください。以前は、他のバージョンとうまく機能せず、リファクタリングpandasによって頭痛の種が発生していました。物事は今改善されました。


こんにちは@DSM。私はあなたが言っていることを聞きますが、私はこのエラーを受け取ります: Traceback (most recent call last): File "./b.py", line 24, in <module> d["D"] = m[d.A] IndexError: unsupported iterator index
mane

1
@mane:urf、それは古いnumpyバグです。あなたのd["D"] = m[d.A.values]ために働きますか?
DSM

277

リストを直接割り当てるだけです。

df['new_col'] = mylist

代替
リストを系列または配列に変換してから、以下を割り当てます。

se = pd.Series(mylist)
df['new_col'] = se.values

または

df['new_col'] = np.array(mylist)

3
pykernel_launcher.py:1: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy """Entry point for launching an IPython kernel.
Ilya

@sparrowはdtypeにpd.Series影響を与えますか?つまり、フロートをフロートとして残し、文字列を文字列として残すのでしょうか?または、リスト内の要素はデフォルトで文字列になりますか?
3kstc 2018

2
@IlyaRusin、これは誤検知であり、この場合は無視できます。詳細情報:stackoverflow.com/questions/20625582/…–
スズメ

1
これは次のように簡略化できます。df['new_col'] = pd.Series(mylist).values
smartse

15

@sparrowのすばらしいソリューションを改善するソリューション。

ましょうDF、あなたのデータセットも、そしてMYLISTあなたがデータフレームに追加する値でリストを。

新しい列を単純にnew_columnと呼びたいとしましょう。

まず、リストをシリーズにします。

column_values = pd.Series(mylist)

次に、挿入機能を使用して列を追加します。この関数には、列を配置する位置を選択できるという利点があります。次の例では、新しい列を左から1番目の位置に配置します(loc = 0を設定することにより)

df.insert(loc=0, column='new_column', value=column_values)

dfのインデックスを1,2,3以外に変更した場合、これは機能しません...その場合、行の間に追加する必要があります:column_values.index = df.index
Guy s

8

まず、作成したデータフレームを作成しましょう。列BとCは関係がないため、無視します。

df = pd.DataFrame({'A': [0, 4, 5, 6, 7, 7, 6,5]})

そしてあなたが望むマッピング:

mapping = dict(enumerate([2,5,6,8,12,16,26,32]))

df['D'] = df['A'].map(mapping)

完了!

print df

出力:

   A   D
0  0   2
1  4  12
2  5  16
3  6  26
4  7  32
5  7  32
6  6  26
7  5  16

1
OPはすでにこれを行う方法を知っていると思います。私が読んだところ、問題はandDの要素から構築されています(「列Aの要素がnの場合、リストのn番目の要素を新しい列に挿入する必要があります。たとえば「D」)AList
DSM

SOはある種のF(*&子守国家になりました。コメントをくれた@DSMに感謝しますが、査読されるまで投稿を修正できませんでした。その後、速すぎたため拒否されました。その後、私は私自身の編集をピアレビューすることができます。そして、より悪い(IMHO)回答が「受け入れられた」ため、手遅れになります。SOには、役に立たないメタ乳母が本当にいます!!!!
Phil Cooper

まあ、私は乳母について話すことはできませんが、あなたのアプローチは長い配列では約1桁遅いことがわかります。もちろん、他の点では、np.array(List)[df.A]との間の選択df["A"].map(dict(enumerate(List)))はほとんどの場合好みの問題です。
DSM

こんにちはフィル、私はあなたの解決策とDSMのコメントを見ただけで、DSMの解決策が私にとってうまく機能したので、それから決してそれに戻ることはありませんでした。しかし、今あなたの解決策を見ると、それも機能します。約200kエントリのデータセットでDSMのソリューションを実行しましたが、他のすべての計算で数秒で実行されます。私はpython-pandasにまったく慣れておらず、個人的にはエレガントで素晴らしいものを探していませんでした。うまくいったものは何でも大丈夫だった。しかし正直なところ、解決策に感謝します。
たてがみ

2

古い質問; しかし、私は常に最速のコードを使用しようとします!

私は6900万のuint64を含む膨大なリストを持っていました。np.array()は私にとって最速でした。

df['hashes'] = hashes
Time spent: 17.034842014312744

df['hashes'] = pd.Series(hashes).values
Time spent: 17.141014337539673

df['key'] = np.array(hashes)
Time spent: 10.724546194076538
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.