python - 使用来自另一个多索引数据帧的 .loc 填充数据帧值的最快方法
问题描述
我有一个数据 框 df1:
key1 key2 val
1 100
2 500
4 400
我也有一个多索引数据 框 df2:
c
a b
1 100 a
2 200 b
3 300 j
4 400 e
5 500 t
我想val
从多索引数据框 df2中填充我的 df1 列
我试过了:
for index,row in df1.iterrows():
try:
data = df2.loc([row['key1'],row['key2'])
df1.loc[(df1.key1 == row['key1']) & (df1.key2 == row['key2']), 'val'] = data
except:
pass
最后,我的 df1 应该是这样的:
key1 key2 val
1 100 a
2 500
4 400 e
但我主要担心的是 df2(多索引 df)的实际长度约为 60-7 万行。
df1 的长度几乎不会是 10 行。(我想重复这个过程,以 df1 包含其他数据)
那么这个 .loc 使用 for 循环是否有效?它是最快的吗?
还是使用 .apply 会更快?
我希望这个迭代是最快的。
以最快的方式运行它有什么线索吗?
解决方案
在 pandas 中最好避免loops
s -iterrows
和apply
(引擎盖下的循环),更好的是矢量化解决方案。
join
与参数一起使用on
:
#for improve performance sort index and columns
df2 = df2.sort_index()
df1 = df1.sort_values(['key1','key2'])
df = df1.join(df2, on=['key1','key2'])
print (df)
key1 key2 val c
0 1 100 NaN a
1 2 500 NaN NaN
2 4 400 NaN e
编辑:
另一种方法是连接MultiIndex
和列值并使用map
:
df2.index = ['{}_{}'.format(a,b) for a, b in df2.index]
print (df2)
c
1_100 a
2_200 b
3_300 j
4_400 e
5_500 t
df1['joined'] = df1['key1'].astype(str) + '_' + df1['key2'].astype(str)
print (df1)
key1 key2 val joined
0 1 100 NaN 1_100
1 2 500 NaN 2_500
2 4 400 NaN 4_400
df1['col'] = df1['joined'].map(df2['c'])
print (df1)
key1 key2 val joined col
0 1 100 NaN 1_100 a
1 2 500 NaN 2_500 NaN
2 4 400 NaN 4_400 e
时间:
np.random.seed(123)
N = 100000
df2 = pd.DataFrame(np.random.randint(10000, size=(N, 3)), columns=list('abc'))
df2 = df2.drop_duplicates(['a','b']).set_index(['a','b'])
print (df2.head())
c
a b
3582 1346 5218
7763 9785 7382
5857 96 6257
6782 4143 4169
5664 942 6368
df1 = df2.iloc[np.random.randint(N, size=10)].reset_index()
df1.columns = ['key1','key2','val']
print (df1)
key1 key2 val
0 5157 9207 283
1 6452 6474 7092
2 1264 5009 5123
3 86 7225 1025
4 7787 5134 637
5 9406 6119 8719
6 7479 1493 1525
7 4098 7248 7618
8 9921 7925 8547
9 2320 764 1564
1.加入未排序MultiIndex
的列:
In [42]: %timeit df1.join(df2, on=['key1','key2'])
100 loops, best of 3: 11.1 ms per loop
2.然后先排序再join(排序中不使用时序):
df2 = df2.sort_index()
In [44]: %timeit df1.join(df2, on=['key1','key2'])
100 loops, best of 3: 10.5 ms per loop
3.map
解决方案,如果仍然相同的数据只运行一次,连接MultiIndex
也不计入计时:
df2.index = ['{}_{}'.format(a,b) for a, b in df2.index]
df1['joined'] = df1['key1'].astype(str) + '_' + df1['key2'].astype(str)
In [51]: %timeit df1['col'] = df1['joined'].map(df2['c'])
1000 loops, best of 3: 371 µs per loop
In [55]: %%timeit
...: df1['joined'] = df1['key1'].astype(str) + '_' + df1['key2'].astype(str)
...: df1['col'] = df1['joined'].map(df2['c'])
...:
1000 loops, best of 3: 1.08 ms per loop
推荐阅读
- c# - WPF C# 绑定来自另一个类的数据
- javascript - 当来自“背景 > 脚本”的脚本试图清除它时,“web_accessible_resources”脚本设置的间隔 ID 没有被清除
- python - 即使 pandas 中没有值也创建额外的行
- c++ - 我可以将表达式存储为双精度吗?(或任何变量)
- c# - ,net core 3.1 AddAuthorization 方法未找到
- c# - 如何防止 MS Word 文档中出现新行?
- amazon-web-services - Cloudfront 403 绕过
- javascript - D3 按钮输入更改数据(堆积条形图)
- file - 方案:使用 open-i/o-file 函数
- c - 斐波那契函数的尾递归版本