Tambahkan kolom dengan nilai konstan ke bingkai data pandas [duplikat]

104

Diberikan DataFrame:

np.random.seed(0)
df = pd.DataFrame(np.random.randn(3, 3), columns=list('ABC'), index=[1, 2, 3])
df

          A         B         C
1  1.764052  0.400157  0.978738
2  2.240893  1.867558 -0.977278
3  0.950088 -0.151357 -0.103219

Apa cara termudah untuk menambahkan kolom baru yang berisi nilai konstan misalnya 0?

          A         B         C  new
1  1.764052  0.400157  0.978738    0
2  2.240893  1.867558 -0.977278    0
3  0.950088 -0.151357 -0.103219    0

Ini adalah solusi saya, tetapi saya tidak tahu mengapa ini menempatkan NaN ke kolom 'baru'?

df['new'] = pd.Series([0 for x in range(len(df.index))])

          A         B         C  new
1  1.764052  0.400157  0.978738  0.0
2  2.240893  1.867558 -0.977278  0.0
3  0.950088 -0.151357 -0.103219  NaN
yemu
sumber
9
jika Anda menggunakan indeks tidak apa-apa. df['new'] = pd.Series([0 for x in range(len(df.index))], index=df.index).
zach
5
juga, pemahaman daftar sama sekali tidak diperlukan di sini. lakukan saja[0] * len(df.index)
acushner
@ Joris, maksud saya bahwa df ['new'] = 0 menunjukkan alasan yang tepat mengapa menetapkan nol ke seluruh kolom, tetapi itu tidak menjelaskan mengapa upaya pertama saya menyisipkan NaN. Ini dijawab oleh Philip Cloud dalam jawaban yang saya terima.
yemu
7
Cukup lakukandf['new'] = 0
flow2k

Jawaban:

22

Alasan hal ini dimasukkan NaNke dalam kolom adalah karena df.indexdan objek sisi Indexkanan Anda berbeda. @zach menunjukkan cara yang tepat untuk menetapkan kolom nol baru. Secara umum, pandascoba lakukan penyelarasan indeks sebanyak mungkin. Satu sisi negatifnya adalah ketika indeks tidak selaras, Anda akan mendapatkan apa NaNpun yang tidak selaras. Bermain-main dengan metode reindexdan alignuntuk mendapatkan beberapa intuisi untuk pekerjaan penyelarasan dengan objek yang memiliki indeks selaras sebagian, total, dan tidak-semua. Misalnya, inilah cara DataFrame.align()bekerja dengan indeks yang rata sebagian:

In [7]: from pandas import DataFrame

In [8]: from numpy.random import randint

In [9]: df = DataFrame({'a': randint(3, size=10)})

In [10]:

In [10]: df
Out[10]:
   a
0  0
1  2
2  0
3  1
4  0
5  0
6  0
7  0
8  0
9  0

In [11]: s = df.a[:5]

In [12]: dfa, sa = df.align(s, axis=0)

In [13]: dfa
Out[13]:
   a
0  0
1  2
2  0
3  1
4  0
5  0
6  0
7  0
8  0
9  0

In [14]: sa
Out[14]:
0     0
1     2
2     0
3     1
4     0
5   NaN
6   NaN
7   NaN
8   NaN
9   NaN
Name: a, dtype: float64
Phillip Cloud
sumber
11
Saya tidak memberi suara negatif tetapi kode Anda tidak memiliki komentar, membuatnya sulit untuk diikuti dengan apa yang Anda coba capai dalam cuplikan
ganti rugi
8
Ini tidak benar-benar menjawab pertanyaan itu. OP menanyakan tentang bagaimana menambahkan kolom baru yang berisi nilai konstan.
cs95
Saya tidak setuju bahwa hanya ada satu pertanyaan di sini. Ada "Bagaimana cara menetapkan nilai konstan ke kolom?" serta "Upaya saya untuk melakukan ini tidak berhasil dengan cara X, mengapa ini berperilaku tidak terduga?" Saya yakin saya telah membahas kedua poin tersebut, yang pertama dengan mengacu pada jawaban lain. Silakan baca semua teks dalam jawaban saya.
Phillip Cloud
Saya pikir masalahnya ada pada pertanyaan, bukan pada jawaban Anda. Ada dua pertanyaan berbeda yang terkandung dalam posting ini dan sebagai hasilnya diperlukan dua jawaban berbeda untuk menjawab pertanyaan tersebut. Saya yakin ini seharusnya ditandai sebagai terlalu luas dan pengepos seharusnya menanyakan dua pertanyaan terpisah.
Kevin
90

Penugasan di tempat yang sangat sederhana: df['new'] = 0

Untuk modifikasi di tempat, lakukan penugasan langsung. Tugas ini disiarkan oleh panda untuk setiap baris.

df = pd.DataFrame('x', index=range(4), columns=list('ABC'))
df

   A  B  C
0  x  x  x
1  x  x  x
2  x  x  x
3  x  x  x

df['new'] = 'y'
# Same as,
# df.loc[:, 'new'] = 'y'
df

   A  B  C new
0  x  x  x   y
1  x  x  x   y
2  x  x  x   y
3  x  x  x   y

Catatan untuk kolom objek

Jika Anda ingin menambahkan kolom daftar kosong, inilah saran saya:

  • Pertimbangkan untuk tidak melakukan ini. objectkolom adalah berita buruk dalam hal kinerja. Pikirkan kembali bagaimana data Anda terstruktur.
  • Pertimbangkan untuk menyimpan data Anda dalam struktur data yang jarang. Informasi selengkapnya: struktur data renggang
  • Jika Anda harus menyimpan kolom daftar, pastikan untuk tidak menyalin referensi yang sama beberapa kali.

    # Wrong
    df['new'] = [[]] * len(df)
    # Right
    df['new'] = [[] for _ in range(len(df))]
    

Menghasilkan salinan: df.assign(new=0)

Jika Anda membutuhkan salinan, gunakan DataFrame.assign:

df.assign(new='y')

   A  B  C new
0  x  x  x   y
1  x  x  x   y
2  x  x  x   y
3  x  x  x   y

Dan, jika Anda perlu menetapkan beberapa kolom dengan nilai yang sama, ini sesederhana,

c = ['new1', 'new2', ...]
df.assign(**dict.fromkeys(c, 'y'))

   A  B  C new1 new2
0  x  x  x    y    y
1  x  x  x    y    y
2  x  x  x    y    y
3  x  x  x    y    y

Tugas beberapa kolom

Terakhir, jika Anda perlu menetapkan beberapa kolom dengan nilai yang berbeda, Anda dapat menggunakan assignkamus.

c = {'new1': 'w', 'new2': 'y', 'new3': 'z'}
df.assign(**c)

   A  B  C new1 new2 new3
0  x  x  x    w    y    z
1  x  x  x    w    y    z
2  x  x  x    w    y    z
3  x  x  x    w    y    z
cs95
sumber
21

Dengan panda modern, Anda dapat melakukan:

df['new'] = 0
Roko Mijic
sumber
1
Dapatkah Anda menunjukkan jawaban spesifik mana yang ketinggalan zaman? Mari tinggalkan komentar di bawah mereka sehingga penulis memiliki kesempatan untuk memperbaiki diri.
cs95
1
Fyi, satu-satunya perbedaan antara jawaban ini dan jawaban cs95 (AKA, me) adalah nama dan nilai kolom. Semua bagiannya ada di sana.
cs95
1
Memang tidak terlalu ketinggalan zaman, tetapi jawaban ini kurang bertele-tele daripada yang lain dan lebih mudah dibaca.
Joey
1
@Joey Tidak dapat membantah logika itu, saya kira jawaban ini lebih cocok untuk orang yang hanya ingin menyalin tempel apa pun yang akan berfungsi, daripada ingin memahami dan mempelajari lebih lanjut tentang perpustakaan. Touche.
cs95
1
@ cs95 ya jawaban Anda memungkinkan orang mempelajari lebih lanjut. Juga df ['new'] = 0 yang disorot dalam judul bagus untuk keterbacaan. Saya telah memberikan suara positif juga. Kurang bertele-tele dari df.apply (lambda x: 0, axis = 1)
Joey
7

Berikut ini satu liner lain yang menggunakan lambda (buat kolom dengan nilai konstan = 10)

df['newCol'] = df.apply(lambda x: 10, axis=1)

sebelum

df
    A           B           C
1   1.764052    0.400157    0.978738
2   2.240893    1.867558    -0.977278
3   0.950088    -0.151357   -0.103219

setelah

df
        A           B           C           newCol
    1   1.764052    0.400157    0.978738    10
    2   2.240893    1.867558    -0.977278   10
    3   0.950088    -0.151357   -0.103219   10
Berikan Shannon
sumber
5
df['newCol'] = 10juga merupakan satu liner (dan lebih cepat). Apa keuntungan menggunakan apply di sini?
cs95
2
tidak mencoba untuk bersaing dengan Anda di sini - hanya menunjukkan pendekatan alternatif.
Grant Shannon
@ cs95 Ini berguna. Saya ingin membuat kolom baru di mana setiap nilai adalah daftar kosong yang terpisah. Hanya metode ini yang berhasil.
Yatharth Agarwal
@YatharthAgarwal Saya akan memberikannya, tetapi juga masuk akal mengingat panda tidak dirancang untuk bekerja dengan baik dengan kolom daftar.
cs95
1
@YatharthAgarwal Jika Anda perlu menetapkan daftar kosong, ini masih merupakan solusi di bawah standar karena menggunakan apply. Cobadf['new'] = [[] for _ in range(len(df))]
cs95