【问题标题】:Proper DataFrame slice modification正确的 DataFrame 切片修改
【发布时间】:2016-01-05 19:37:35
【问题描述】:

我正在尝试从一组行中修改一组列,当然我会收到以下警告:

A value is trying to be set on a copy of a slice from a DataFrame

我看到了一个类似的问题here,但我无法理解它。

所以如果我们按照这个示例代码:

from random import random as rd
ex= pd.DataFrame([{"group": ["a","b"][int(round(rd()))], "colA": rd()*10, "colB": rd()*10, "colC": rd()*10,  "colD": rd()*10} for _ in range(20)])
cols = [col for col in ex.columns if col != "group"]

我只想修改属于 group a 的行和列 cols 上的行,对此我有点直觉地尝试(并收到警告警告):

ex[ex["group"]=="a"][cols] = ex[ex["group"]=="a"][cols]/ex.ix[0,cols]

列数匹配并且具有相同的标签,所以我想知道是否必须像这样一一进行:

for idx in ex[ex["group"]=="a"].index:
    for col in cols:
        ex.ix[idx, col]=ex.ix[idx, col]/ex.ix[0,col]

这当然可行,但感觉像是退后一步。那么做这样的事情的正确方法是什么?

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    IIUC 您可以使用您的布尔条件 .loc 一步完成此操作并传递 cols 列表:

    In [110]:
    from random import random as rd
    ex= pd.DataFrame([{"group": ["a","b"][int(round(rd()))], "colA": rd()*10, "colB": rd()*10, "colC": rd()*10,  "colD": rd()*10} for _ in range(20)])
    cols = [col for col in ex.columns if col != "group"]
    ex
    
    Out[110]:
            colA      colB      colC      colD group
    0   5.895114  3.961007  0.589091  9.846131     a
    1   1.789049  7.532745  2.767378  9.144689     b
    2   1.218778  2.715299  3.626688  6.516540     a
    3   9.327049  3.207037  4.513850  1.910565     b
    4   1.822876  0.049689  0.794706  8.463579     a
    5   1.451741  6.045066  6.575130  4.882635     b
    6   6.741825  4.253489  2.162466  1.050275     a
    7   5.186613  3.401384  1.055468  4.060071     a
    8   0.921352  8.076272  6.727293  3.219364     a
    9   3.209232  8.883085  9.696195  4.089006     b
    10  0.970030  6.412611  5.377420  5.475744     b
    11  7.905807  4.576925  6.991989  2.974597     b
    12  4.907642  7.123328  9.851058  2.337944     b
    13  1.191606  2.636071  5.740342  3.301008     b
    14  1.454777  3.086801  3.573110  1.402692     b
    15  3.253882  1.853393  5.156287  8.268881     b
    16  4.779060  4.689739  1.228976  6.339238     b
    17  7.950160  4.973974  4.304821  4.492152     b
    18  0.581628  6.860053  2.974577  6.542594     a
    19  6.872025  9.216597  0.936447  5.518941     b
    
    In [111]:    
    ex.loc[ex['group']=='a', cols] /= ex.iloc[0][cols]
    ex
    
    Out[111]:
            colA      colB       colC      colD group
    0   1.000000  1.000000   1.000000  1.000000     a
    1   1.789049  7.532745   2.767378  9.144689     b
    2   0.206744  0.685507   6.156417  0.661838     a
    3   9.327049  3.207037   4.513850  1.910565     b
    4   0.309218  0.012545   1.349039  0.859584     a
    5   1.451741  6.045066   6.575130  4.882635     b
    6   1.143629  1.073840   3.670853  0.106669     a
    7   0.879816  0.858717   1.791690  0.412352     a
    8   0.156291  2.038944  11.419789  0.326967     a
    9   3.209232  8.883085   9.696195  4.089006     b
    10  0.970030  6.412611   5.377420  5.475744     b
    11  7.905807  4.576925   6.991989  2.974597     b
    12  4.907642  7.123328   9.851058  2.337944     b
    13  1.191606  2.636071   5.740342  3.301008     b
    14  1.454777  3.086801   3.573110  1.402692     b
    15  3.253882  1.853393   5.156287  8.268881     b
    16  4.779060  4.689739   1.228976  6.339238     b
    17  7.950160  4.973974   4.304821  4.492152     b
    18  0.098663  1.731896   5.049437  0.664484     a
    19  6.872025  9.216597   0.936447  5.518941     b
    

    时间

    In [112]:
    %%timeit
    for idx in ex[ex["group"]=="a"].index:
        for col in cols:
            ex.ix[idx, col]=ex.ix[idx, col]/ex.ix[0,col]
    100 loops, best of 3: 11 ms per loop
    
    In [113]:
    %timeit ex.loc[ex['group']=='a', cols] /= ex.iloc[0][cols]
    100 loops, best of 3: 5.3 ms per loop
    

    因此,在您的小样本量下,我的方法速度提高了 2 倍以上,我希望它在矢量化后能够更好地扩展更大的数据集

    【讨论】:

    • 作为更新:当使用浮动的列名时,例如[1.1, 2.1, 3.4, 4.5] 而不是 ["colA", "colB", "colC", "colD"] 切片将在您想要查看时起作用,但是如果要对该切片进行归因,它将不起作用!
    • 对列或索引值使用浮点数通常不是一个好主意
    猜你喜欢
    • 2019-05-08
    • 2016-10-20
    • 2017-12-11
    • 2017-03-28
    • 2017-05-29
    • 1970-01-01
    • 2022-10-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多