【问题标题】:Replace dataframe row with partial dictionary用部分字典替换数据框行
【发布时间】:2020-11-13 03:09:42
【问题描述】:

我想用只包含几个键的 dict 替换数据框的一行:

     A   B   C   D
0   45  88  44  92
1   62  34   2  86
2   85  65  11  31
3   74  43  42  56
4   90  38  34  93
5    0  94  45  10
6   58  23  23  60

d = {'A':13, 'D':3}

我试过了:

df.loc[line_to_replace] = pd.Series(d)

但是得到了:

---> 26     df.loc[line_to_replace] = pd.Series(dict_replacing) # bad idea, I lose the information about the keys of where to insert

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\indexing.py in __setitem__(self, key, value)
    669             key = com.apply_if_callable(key, self.obj)
    670         indexer = self._get_setitem_indexer(key)
--> 671         self._setitem_with_indexer(indexer, value)
    672 
    673     def _validate_key(self, key, axis: int):

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\indexing.py in _setitem_with_indexer(self, indexer, value)
   1017                     if len(labels) != len(value):
   1018                         raise ValueError(
-> 1019                             "Must have equal len keys and value "
   1020                             "when setting with an iterable"
   1021                         )

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

更新

我尝试更新的实际数据框出现以下错误:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-1215-ca5f285affa4> in <module>
      2     for dic in sets:
      3         if 'https' not in dic:
----> 4             isGrid(dic)

<ipython-input-1214-3f69d41d4a8a> in isGrid(dic)
     10         if len(answers) > 1:
     11             # find the line in df and replace the line where it matches by the lines
---> 12             update_lines(dic, df)
     13     except TypeError:
     14         print("truc")

<ipython-input-1214-3f69d41d4a8a> in update_lines(dic, df)
     24         answers.append(reduce(lambda a,b: a+b,[ind_answers[i] for x in range(len(questions))]))
     25     dict_replacing = {"Questions": questions,"Answer0":answers[0],"Answer1":answers[1],"Answer2":answers[2],"Answer3":answers[3],"Answer4":answers[4]}
---> 26     df.loc[line_to_replace, dict_replacing.keys()] = dict_replacing.values()

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\indexing.py in __setitem__(self, key, value)
    669             key = com.apply_if_callable(key, self.obj)
    670         indexer = self._get_setitem_indexer(key)
--> 671         self._setitem_with_indexer(indexer, value)
    672 
    673     def _validate_key(self, key, axis: int):

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\indexing.py in _setitem_with_indexer(self, indexer, value)
   1022 
   1023                     for item, v in zip(labels, value):
-> 1024                         setter(item, v)
   1025             else:
   1026 

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\indexing.py in setter(item, v)
    960                     s._consolidate_inplace()
    961                     s = s.copy()
--> 962                     s._data = s._data.setitem(indexer=pi, value=v)
    963                     s._maybe_update_cacher(clear=True)
    964 

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\internals\managers.py in setitem(self, **kwargs)
    559 
    560     def setitem(self, **kwargs):
--> 561         return self.apply("setitem", **kwargs)
    562 
    563     def putmask(self, **kwargs):

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\internals\managers.py in apply(self, f, filter, **kwargs)
    440                 applied = b.apply(f, **kwargs)
    441             else:
--> 442                 applied = getattr(b, f)(**kwargs)
    443             result_blocks = _extend_blocks(applied, result_blocks)
    444 

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\internals\blocks.py in setitem(self, indexer, value)
    876 
    877         # length checking
--> 878         check_setitem_lengths(indexer, value, values)
    879         exact_match = (
    880             len(arr_value.shape)

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\indexers.py in check_setitem_lengths(indexer, value, values)
    113             ):
    114                 raise ValueError(
--> 115                     "cannot set using a list-like indexer "
    116                     "with a different length than the value"
    117                 )

ValueError: cannot set using a list-like indexer with a different length than the value

这是我要更新的数据框行:

line_to_replace [21]
df.loc[line_to_replace, list(dict_replacing.keys())]: 
                                           Questions         Answer0  \
21  What are new offers you are most interested in?  Not Interested   

                Answer1     Answer2            Answer3                 Answer4  
21  Somewhat Interested  Interested  Highly Interested  Very Highly Interested  

这里是包含应该更新数据框的值的字典:

 list(dict_replacing.values()): 
 [['The airline/company you fly with', 'The departure airport', 'Duration of flight/route', 'Price', 'Baggage policy', 'Environmental impacts'], ['Not Interested', 'Not Interested', 'Not Interested', 'Not Interested', 'Not Interested', 'Not Interested'], ['Somewhat Interested', 'Somewhat Interested', 'Somewhat Interested', 'Somewhat Interested', 'Somewhat Interested', 'Somewhat Interested'], ['Interested', 'Interested', 'Interested', 'Interested', 'Interested', 'Interested'], ['Highly Interested', 'Highly Interested', 'Highly Interested', 'Highly Interested', 'Highly Interested', 'Highly Interested'], ['Very Highly Interested', 'Very Highly Interested', 'Very Highly Interested', 'Very Highly Interested', 'Very Highly Interested', 'Very Highly Interested']]

【问题讨论】:

    标签: python-3.x pandas dataframe dictionary


    【解决方案1】:

    你可以这样做:

    df.loc[line_to_update, d.keys()] = d.values()
    

    【讨论】:

    • 感谢您的回答 :) 但是我用您的方法得到了ValueError: cannot set using a list-like indexer with a different length than the value
    • 你的line_to_replace是什么?
    • 具有匹配行的数组。现在是:[21]
    【解决方案2】:

    您可以将DataFrame.loc 与按列表设置或标量与键匹配列名称和字典设置值一起使用:

    d = {'A':13, 'D':3}
    
    line_to_replace = [1,5]
    df.loc[line_to_replace, d.keys()] = d.values()
    print (df)
        A   B   C   D
    0  45  88  44  92
    1  13  34   2   3
    2  85  65  11  31
    3  74  43  42  56
    4  90  38  34  93
    5  13  94  45   3
    6  58  23  23  60
    

    line_to_replace = 1
    df.loc[line_to_replace, d.keys()] = d.values()
    print (df)
        A   B   C   D
    0  45  88  44  92
    1  13  34   2   3
    2  85  65  11  31
    3  74  43  42  56
    4  90  38  34  93
    5   0  94  45  10
    6  58  23  23  60
    

    【讨论】:

    • 感谢您的回答 :) 但是我用您的方法得到了ValueError: cannot set using a list-like indexer with a different length than the value
    • @RevolucionforMonica - 你能测试一下df.loc[line_to_replace, list(d.keys())] = list(d.values()) 吗?
    • 是的,只是给了同样的... :'(
    • @RevolucionforMonica - 可以升级熊猫吗?可能是版本相关的问题。
    • 试试,我的版本是Version: 1.0.3
    猜你喜欢
    • 2021-09-03
    • 1970-01-01
    • 2017-09-09
    • 2018-01-28
    • 1970-01-01
    • 2021-01-24
    • 1970-01-01
    • 2020-02-15
    • 2012-12-30
    相关资源
    最近更新 更多