Python pandas แทรกรายการลงในเซลล์


111

ฉันมีรายการ 'abc' และ dataframe 'df':

abc = ['foo', 'bar']
df =
    A  B
0  12  NaN
1  23  NaN

ฉันต้องการแทรกรายการลงในเซลล์ 1B ดังนั้นฉันต้องการผลลัพธ์นี้:

    A  B
0  12  NaN
1  23  ['foo', 'bar']

โฮฉันจะทำอย่างนั้นได้ไหม?

1) ถ้าฉันใช้สิ่งนี้:

df.ix[1,'B'] = abc

ฉันได้รับข้อความแสดงข้อผิดพลาดต่อไปนี้:

ValueError: Must have equal len keys and value when setting with an iterable

เนื่องจากพยายามแทรกรายการ (ที่มีสององค์ประกอบ) ลงในแถว / คอลัมน์ แต่ไม่เข้าไปในเซลล์

2) ถ้าฉันใช้สิ่งนี้:

df.ix[1,'B'] = [abc]

จากนั้นจะแทรกรายการที่มีองค์ประกอบเดียวคือรายการ 'abc' ( [['foo', 'bar']])

3) ถ้าฉันใช้สิ่งนี้:

df.ix[1,'B'] = ', '.join(abc)

จากนั้นจะแทรกสตริง: ( foo, bar) แต่ไม่ใช่รายการ

4) ถ้าฉันใช้สิ่งนี้:

df.ix[1,'B'] = [', '.join(abc)]

จากนั้นจะแทรกรายการ แต่มีเพียงองค์ประกอบเดียว ( ['foo, bar']) แต่ไม่ใช่สองรายการตามที่ฉันต้องการ ( ['foo', 'bar'])

ขอบคุณที่ช่วยเหลือ!


แก้ไข

ดาต้าเฟรมใหม่ของฉันและรายการเก่า:

abc = ['foo', 'bar']
df2 =
    A    B         C
0  12  NaN      'bla'
1  23  NaN  'bla bla'

ดาต้าเฟรมอื่น:

df3 =
    A    B         C                    D
0  12  NaN      'bla'  ['item1', 'item2']
1  23  NaN  'bla bla'        [11, 12, 13]

ฉันต้องการใส่ 'abc' รายการลงในและdf2.loc[1,'B'] / หรือdf3.loc[1,'B']

หากดาต้าเฟรมมีคอลัมน์ที่มีเฉพาะค่าจำนวนเต็มและ / หรือค่า NaN และ / หรือค่ารายการการแทรกรายการลงในเซลล์จะทำงานได้อย่างสมบูรณ์ หากดาต้าเฟรมมีคอลัมน์ที่มีเฉพาะค่าสตริงและ / หรือค่า NaN และ / หรือค่ารายการการแทรกรายการลงในเซลล์จะทำงานได้อย่างสมบูรณ์ แต่ถ้าดาต้าเฟรมมีคอลัมน์ที่มีค่าจำนวนเต็มและสตริงและคอลัมน์อื่น ๆ ข้อความแสดงข้อผิดพลาดจะปรากฏขึ้นหากฉันใช้สิ่งนี้: df2.loc[1,'B'] = abcหรือdf3.loc[1,'B'] = abc.

ดาต้าเฟรมอื่น:

df4 =
          A     B
0      'bla'  NaN
1  'bla bla'  NaN

เม็ดมีดเหล่านี้ทำงานได้อย่างสมบูรณ์: df.loc[1,'B'] = abcหรือdf4.loc[1,'B'] = abc.


1
คุณใช้แพนด้ารุ่นอะไร ต่อไปนี้ทำงานโดยใช้แพนด้า0.15.0:df.loc[1,'b'] = ['foo','bar']
EdChum

ขอบคุณ! ฉันใช้ Python 2.7 และฉันลองแพนด้า 0.14.0 และ 0.15.0 และใช้ได้กับข้อมูลทดสอบด้านบน แต่จะเกิดอะไรขึ้นถ้าฉันมีคอลัมน์ 'C' พร้อมกับค่าจำนวนเต็ม? 'A' มีสตริง มีคอลัมน์จำนวนเต็มและคอลัมน์ srting ฉันได้รับข้อผิดพลาดเดียวกัน: ValueError: ต้องมีคีย์และค่า len เท่ากันเมื่อตั้งค่าด้วยการทำซ้ำ
ragesz

คุณจะต้องโพสต์ข้อมูลและรหัสเพื่ออธิบายและแสดงความหมาย
EdChum

คำตอบ:


130

เนื่องจากset_valueได้เลิกใช้งานแล้วตั้งแต่เวอร์ชัน 0.21.0 ตอนนี้คุณควรใช้atไฟล์. มันสามารถแทรกรายการลงในเซลล์โดยไม่ต้องยกValueErrorเป็นlocไม่ ผมคิดว่านี่เป็นเพราะat มักจะหมายถึงค่าเดียวในขณะที่locสามารถอ้างถึงค่าเช่นเดียวกับแถวและคอลัมน์

df = pd.DataFrame(data={'A': [1, 2, 3], 'B': ['x', 'y', 'z']})

df.at[1, 'B'] = ['m', 'n']

df =
    A   B
0   1   x
1   2   [m, n]
2   3   z

นอกจากนี้คุณยังจะต้องให้แน่ใจว่าคอลัมน์dtype=objectที่คุณกำลังใส่ลงในมี ตัวอย่างเช่น

>>> df = pd.DataFrame(data={'A': [1, 2, 3], 'B': [1,2,3]})
>>> df.dtypes
A    int64
B    int64
dtype: object

>>> df.at[1, 'B'] = [1, 2, 3]
ValueError: setting an array element with a sequence

>>> df['B'] = df['B'].astype('object')
>>> df.at[1, 'B'] = [1, 2, 3]
>>> df
   A          B
0  1          1
1  2  [1, 2, 3]
2  3          3

4
ฉันต้องแน่ใจว่า dataframe dtype ดั้งเดิมถูกตั้งค่าเป็นคัดค้านเพื่อให้สิ่งนี้ใช้งานได้:df = pd.DataFrame(data, dtype=object)
Takver

2
ที่ต้องการดัชนี ฉันจะอ้างถึงแถวโดยใช้ค่าแอตทริบิวต์อื่นที่ตรงกันได้อย่างไร เช่น: สำหรับแถวที่มี A = 2 ในตัวอย่างข้างต้น?
bikashg

9
นี้จะส่งกลับข้อผิดพลาดอื่นValueError: setting an array element with a sequence.; ดูคำตอบโดย @ cs95 หากคุณได้รับข้อผิดพลาด
Blaszard

41

df3.set_value(1, 'B', abc)ใช้ได้กับดาต้าเฟรมใด ๆ ดูแลชนิดข้อมูลของคอลัมน์ 'B' เช่น. ไม่สามารถแทรกรายการลงในคอลัมน์ลอยในกรณีdf['B'] = df['B'].astype(object)นั้นสามารถช่วยได้


6
โปรดทราบว่าคำสั่งนี้ได้รับการเลิกใช้ มีการอัปเดตอยู่ด้านล่าง
Thomas

35

นุ่น> = 0.21

set_valueเลิกใช้งานแล้ว ตอนนี้คุณสามารถใช้DataFrame.atเพื่อตั้งค่าตามป้ายกำกับและDataFrame.iatตั้งค่าตามตำแหน่งจำนวนเต็ม

การตั้งค่าเซลล์ด้วยat/iat

# Setup
df = pd.DataFrame({'A': [12, 23], 'B': [['a', 'b'], ['c', 'd']]})
df

    A       B
0  12  [a, b]
1  23  [c, d]

df.dtypes

A     int64
B    object
dtype: object

หากคุณต้องการกำหนดค่าในแถวที่สองของ "B" เป็นรายการใหม่ให้ใช้DataFrane.at:

df.at[1, 'B'] = ['m', 'n']
df

    A       B
0  12  [a, b]
1  23  [m, n]

คุณยังสามารถกำหนดตามตำแหน่งจำนวนเต็มโดยใช้ DataFrame.iat

df.iat[1, df.columns.get_loc('B')] = ['m', 'n']
df

    A       B
0  12  [a, b]
1  23  [m, n]

ถ้าได้ValueError: setting an array element with a sequenceอะไร?

ฉันจะพยายามจำลองสิ่งนี้ด้วย:

df

    A   B
0  12 NaN
1  23 NaN

df.dtypes

A      int64
B    float64
dtype: object

df.at[1, 'B'] = ['m', 'n']
# ValueError: setting an array element with a sequence.

นี่เป็นเพราะวัตถุของคุณเป็นfloat64dtype ในขณะที่รายการเป็นobjects ดังนั้นจึงมีความไม่ตรงกันที่นั่น สิ่งที่คุณต้องทำในสถานการณ์นี้คือการแปลงคอลัมน์เป็นวัตถุก่อน

df['B'] = df['B'].astype(object)
df.dtypes

A     int64
B    object
dtype: object

จากนั้นใช้งานได้:

df.at[1, 'B'] = ['m', 'n']
df

    A       B
0  12     NaN
1  23  [m, n]

เป็นไปได้ แต่แฮกเกอร์

ยิ่งไปกว่านั้นฉันพบว่าคุณสามารถแฮ็คDataFrame.locเพื่อให้ได้สิ่งที่คล้ายกันหากคุณส่งผ่านรายการที่ซ้อนกัน

df.loc[1, 'B'] = [['m'], ['n'], ['o'], ['p']]
df

    A             B
0  12        [a, b]
1  23  [m, n, o, p]

คุณสามารถอ่านเพิ่มเติมเกี่ยวกับสาเหตุที่ใช้งานได้ที่นี่



2

งานด่วน

เพียงใส่รายชื่อไว้ในรายการใหม่เช่นเดียวกับ col2 ในกรอบข้อมูลด้านล่าง เหตุผลที่มันใช้งานได้คือ python ใช้รายการภายนอก (ของรายการ) และแปลงเป็นคอลัมน์ราวกับว่ามีรายการสเกลาร์ปกติซึ่งเป็นรายการในกรณีของเราไม่ใช่สเกลาร์ปกติ

mydict={'col1':[1,2,3],'col2':[[1, 4], [2, 5], [3, 6]]}
data=pd.DataFrame(mydict)
data


   col1     col2
0   1       [1, 4]
1   2       [2, 5]
2   3       [3, 6]

1

นอกจากนี้ยังได้รับ

ValueError: Must have equal len keys and value when setting with an iterable,

การใช้. at แทนที่จะเป็น. loc ไม่ได้สร้างความแตกต่างใด ๆ ในกรณีของฉัน แต่การบังคับใช้ประเภทข้อมูลของคอลัมน์ดาต้าเฟรมทำให้เคล็ดลับ:

df['B'] = df['B'].astype(object)

จากนั้นฉันสามารถตั้งค่ารายการอาร์เรย์จำนวนนับและทุกประเภทเป็นค่าเซลล์เดียวในดาต้าเฟรมของฉัน


0

ฉันมีวิธีแก้ปัญหาที่ค่อนข้างง่ายในการนำไปใช้

สร้างคลาสชั่วคราวเพื่อตัดอ็อบเจ็กต์รายการและเรียกค่าจากคลาสในภายหลัง

นี่คือตัวอย่างที่ใช้ได้จริง:

  1. สมมติว่าคุณต้องการแทรก list object ลงใน dataframe
df = pd.DataFrame([
    {'a': 1},
    {'a': 2},
    {'a': 3},
])

df.loc[:, 'b'] = [
    [1,2,4,2,], 
    [1,2,], 
    [4,5,6]
] # This works. Because the list has the same length as the rows of the dataframe

df.loc[:, 'c'] = [1,2,4,5,3] # This does not work. 

>>> ValueError: Must have equal len keys and value when setting with an iterable

## To force pandas to have list as value in each cell, wrap the list with a temporary class.

class Fake(object):
    def __init__(self, li_obj):
        self.obj = li_obj

df.loc[:, 'c'] = Fake([1,2,5,3,5,7,]) # This works. 

df.c = df.c.apply(lambda x: x.obj) # Now extract the value from the class. This works. 

การสร้างคลาสปลอมเพื่อทำเช่นนี้อาจดูเหมือนยุ่งยาก แต่ก็มีแอปพลิเคชันที่ใช้ได้จริง ตัวอย่างเช่นคุณสามารถใช้applyเมื่อค่าที่ส่งคืนเป็นรายการ

โดยปกติแล้วหมีแพนด้าจะปฏิเสธที่จะแทรกรายการลงในเซลล์ แต่ถ้าคุณใช้วิธีนี้คุณสามารถบังคับแทรกได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.