for i, row in dset.iterrows():
hteam = row['home']
vteam = row['visitor']
row['hlastwin'] = won_last[hteam]
row['vlastwin'] = won_last[vteam]
dset.iloc[i] = row
如上,dset 是一个 DataFrame,遍历每行并为每行增加两个元素,期望遍历结束后 dset 应该增加两列,但实际 dset 没有变化,最后一行代码为啥没效果,有大神能说一下原因吗(搜了一通没啥结果。。),多谢~
1
shidenggui 2018-01-11 23:40:00 +08:00
应该这样写是可以的 dset.assign(hlastwin=lambda x: won_last[x.home], vlastwin=lambda x: won_last[x.visitor])
|
2
imn1 2018-01-11 23:50:29 +08:00 1
iloc/loc 等一般只能用于读取,应该只是类似一个 copy 的性质
改变 df 要另外赋值 另外,这样轮循有点笨啊,应该整列复制,或者 join/merge |
3
zeq 2018-01-12 00:38:51 +08:00
```
dest['hlastwin'] = dest['home'].map(lambda h: won_last[h]) ``` 大概是这么一个思路 |
4
neoblackcap 2018-01-12 09:23:06 +08:00
上面几楼都说了,我加一句,pandas 是调用 numpy 的接口的,因此不要自己写循环。自己的循环是没有 Pandas 里面的对 dataframe 的操作快的。
|
5
fcfangcc 2018-01-12 09:51:50 +08:00
dset.loc[:, 'hlastwin'] = [won_last[i] for i in dset['home'].values]
dset.loc[:, 'vlastwin'] = [won_last[i] for i in dset['visitor'].values] |
6
zyhuang 2018-01-12 09:54:56 +08:00
```
import pandas as pd import numpy as np won_last = pd.DataFrame({'lastwin':["lastwin_{}".format(i) for i in range(10000)]}) dset = pd.DataFrame(np.random.randint(10000, size=(10000, 2)), columns=['home', 'visitor']) In [2]: %timeit dset.merge(won_last, left_on='home', right_index=True,how='left').merge(won_last, left_on='visitor', right_index=True,how='left', suffixes="hv") 7.16 ms ± 340 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) In [3]: %timeit dset.assign(hlastwin=lambda x: [won_last.lastwin[ii] for ii in x.home], vlastwin=lambda x: [won_last.lastwin[ii] for ii in x.visitor]) 355 ms ± 34.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) ``` |
8
focusheart 2018-01-12 22:53:59 +08:00
你问的 iloc 那句不起作用,可以按楼上说的改,比如:
dset[i, 'hlastwin'] = won_last[hteam] 另外,看你的程序意思是每次循环里要给当前 row 填一个“主队上次赢”,“客队上次赢”这样的字段? 由于每个 row 都依赖上一次某条的记录,所以 merge 不太容易吧。 如果是这个情况的话,用 pandas 原地修改 dset 会比较慢,可以新开一个 list 来存;或者原始数据不放 pandas,直接用 list。 这样用 for 循环遍历的表现可能会好一些。 最后,这样一边迭代 dset,同时一边又修改 dset,感觉不太好。建议迭代 dset 的时候不要原地修改,而是将新 row 的数据放在其他变量里。 |