Python pandaları bir hücreye liste ekler


111

Bir 'abc' listem ve bir veri çerçevem ​​'df' var:

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

Listeyi 1B hücresine eklemek istiyorum, bu nedenle şu sonucu istiyorum:

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

Bunu nasıl yapabilirim?

1) Bunu kullanırsam:

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

Aşağıdaki hata mesajını alıyorum:

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

çünkü listeyi (iki öğesi olan) bir satıra / sütuna eklemeye çalışır, ancak bir hücreye değil.

2) Bunu kullanırsam:

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

daha sonra, 'abc' listesi ( [['foo', 'bar']]) olan yalnızca bir öğesi olan bir liste ekler .

3) Bunu kullanırsam:

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

daha sonra bir dize ekler: ( foo, bar) ama liste eklemez.

4) Bunu kullanırsam:

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

sonra bir liste ekler, ancak yalnızca bir öğesi ( ['foo, bar']) vardır, istediğim gibi iki öğe yoktur ( ['foo', 'bar']).

Yardım için teşekkürler!


DÜZENLE

Yeni veri çerçevem ​​ve eski liste:

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

Başka bir veri çerçevesi:

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

'Abc' listesini df2.loc[1,'B']ve / veya içine eklemek istiyorum df3.loc[1,'B'].

Veri çerçevesinin yalnızca tamsayı değerleri ve / veya NaN değerleri ve / veya liste değerleri olan sütunları varsa, bir hücreye bir liste eklemek mükemmel şekilde çalışır. Veri çerçevesinin yalnızca dize değerleri ve / veya NaN değerleri ve / veya liste değerleri olan sütunları varsa, bir hücreye bir liste eklemek mükemmel şekilde çalışır. Ancak veri çerçevesinin tam sayı ve dize değerleri ve diğer sütunları olan sütunları varsa, bunu kullanırsam hata mesajı görünür: df2.loc[1,'B'] = abcveya df3.loc[1,'B'] = abc.

Başka bir veri çerçevesi:

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

Bu ekler mükemmel çalışır: df.loc[1,'B'] = abcveya df4.loc[1,'B'] = abc.


1
Pandaların hangi sürümünü kullanıyorsunuz? aşağıdakiler pandalar kullanılarak çalıştı 0.15.0:df.loc[1,'b'] = ['foo','bar']
EdChum

Teşekkür ederim! Python 2.7 kullanıyorum ve pandalar 0.14.0 ve 0.15.0'ı denedim ve yukarıdaki test verileriyle çalıştı. Peki ya bazı tamsayı değerlerine sahip bir 'C' sütunum varsa? 'A' dizelere sahiptir. Bir tamsayı sütununa ve bir srting sütununa sahip olmak aynı hatayı alıyorum: ValueError: Yinelenebilir ile ayarlarken eşit uzunluk anahtarlarına ve değere sahip olmalıdır
ragesz

Ne demek istediğinizi açıklamak ve göstermek için veri ve kod göndermeniz gerekecek
EdChum

Yanıtlar:


130

Yana set_valueolmuştur kaldırılmış sürümü 0.21.0 beri, artık kullanmalıdır at. Bir hücreye bir listeyi ValueErrorolduğu gibi yükseltmeden ekleyebilir loc. Sanırım bunun nedeni, at her zaman tek bir değere locatıfta bulunurken , değerlerin yanı sıra satırlara ve sütunlara da başvurabilir.

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

Ayrıca eklediğiniz sütunun sahip olduğundan da emin olmanız gerekir dtype=object. Örneğin

>>> 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
Bunun çalışması için orijinal veri çerçevesi dtype'nin nesneye ayarlandığından emin olmalıydım:df = pd.DataFrame(data, dtype=object)
Takver

2
at'ın bir dizine ihtiyacı var. Başka bir öznitelik değeri eşleşmesini kullanarak satıra nasıl başvurabilirim; örneğin: yukarıdaki örnekte A = 2 olan satır için?
bikashg

9
Bu başka bir hata döndürür ValueError: setting an array element with a sequence.; Hatayı alırsanız @ cs95 tarafından verilen yanıta bakın.
Blaszard

41

df3.set_value(1, 'B', abc)herhangi bir veri çerçevesi için çalışır. 'B' sütununun veri türüne dikkat edin. Örneğin. float sütuna bir liste eklenemez, bu durumda df['B'] = df['B'].astype(object)yardımcı olabilir.


6
Bu komutun kullanımdan kaldırıldığını unutmayın . Hemen aşağıda bir güncelleme var.
Thomas

35

Pandalar> = 0.21

set_valuekullanımdan kaldırıldı. Artık DataFrame.atetikete DataFrame.iatgöre ayarlamak ve tam sayı konumuna göre ayarlamak için kullanabilirsiniz .

Hücre Değerleri ile ayarlama 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" nin ikinci satırında yeni bir liste olarak bir değer ayarlamak isterseniz, şunu kullanın DataFrane.at:

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

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

Kullanarak tamsayı konumuna göre de ayarlayabilirsiniz. DataFrame.iat

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

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

Ya alırsam ValueError: setting an array element with a sequence?

Bunu şununla yeniden oluşturmaya çalışacağım:

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.

Bunun nedeni, nesnenizin float64dtype olması, listelerin objects olması, dolayısıyla orada bir uyumsuzluk var. Bu durumda yapmanız gereken şey, önce sütunu nesneye dönüştürmektir.

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

A     int64
B    object
dtype: object

Ardından çalışır:

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

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

Mümkün, Ama Hacky

Daha da tuhaf, DataFrame.lociç içe geçmiş listeleri geçerseniz benzer bir şey elde etmek için geçebileceğinizi fark ettim.

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

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

Bunun neden işe yaradığı hakkında daha fazla bilgiyi buradan okuyabilirsiniz .



2

Hızlı çalışma

Aşağıdaki veri çerçevesinde col2 için yapıldığı gibi, listeyi yeni bir listeye dahil edin. Çalışmasının nedeni, python'un dış listeyi (listelerin) alması ve normal skaler öğeler içeriyormuş gibi bir sütuna dönüştürmesidir, bu bizim durumumuzda normal skaler olmayan listelerdir.

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

Ayrıca alıyorum

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

.loc yerine .at kullanmak benim durumumda herhangi bir fark yaratmadı, ancak veri çerçevesi sütununun veri türünü zorlamak hile yaptı:

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

Sonra listeleri, numpy dizisini ve her türlü şeyi veri çerçevelerimde tek hücre değerleri olarak ayarlayabilirim.


0

Uygulaması oldukça basit bir çözümüm var.

Yalnızca liste nesnesini sarmak ve daha sonra sınıftan değeri çağırmak için geçici bir sınıf oluşturun.

İşte pratik bir örnek:

  1. Veri çerçevesine liste nesnesi eklemek istediğinizi varsayalım.
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. 

Bunu yapmak için sahte bir sınıf oluşturmak zahmetli görünebilir, ancak bazı pratik uygulamalara sahip olabilir. Örneğin apply, dönüş değeri liste olduğunda bunu kullanabilirsiniz .

Pandalar normalde bir hücreye liste eklemeyi reddeder, ancak bu yöntemi kullanırsanız, eklemeyi zorlayabilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.