正确的 DataFrame 切片修改
Posted
技术标签:
【中文标题】正确的 DataFrame 切片修改【英文标题】:Proper DataFrame slice modification 【发布时间】: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]
这当然可行,但感觉像是退后一步。那么做这样的事情的正确方法是什么?
【问题讨论】:
【参考方案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"]
切片将在您想要查看时起作用,但是如果要对该切片进行归因,它将不起作用!
对列或索引值使用浮点数通常不是一个好主意以上是关于正确的 DataFrame 切片修改的主要内容,如果未能解决你的问题,请参考以下文章
将 Pandas DataFrame 切片成新的 DataFrame
从 MultiIndex DataFrame 为切片分配新值
数据分析2 numpy(ndarray数组,属性,创建,索引切片,运算,函数,随机数), Pandas(Series创建,缺失值处理,特性,索引,DataFrame)