- 为了更新
df_list 中的每个数据帧,必须对其进行正确索引,以便可以将新列分配给list 中的正确数据帧,这是通过使用enumerate 完成的。
- 在显示的 3 个选项中,
.applymap(len) 是 10 万行数据帧的最快选项。
import pandas as pd
# create sample data
data = {'test': range(3), 'name': ['a', 'bc', 'def'], 'address': ['add1', 'add11', 'add111'],
'email': ['i_am_lame_4_not_providing_my_own_sample_dataframe@lameduck.com', 'xyz@lameduck.com', 'wxyz@lamerduck.com']}
df1 = pd.DataFrame(data)
df2 = pd.DataFrame(data)
df_list = [df1, df2]
columns = ['name', 'address', 'email']
newcolumns = ['name_length', 'address_length', 'email_length']
# iterate through list of dataframes and add _length columns
for i, df in enumerate(df_list):
# create the new columns and assign them to the correct dataframe in the list
df_list[i][newcolumns] = df[columns].applymap(len)
# display(df1)
test name address email name_length address_length email_length
0 0 a add1 i_am_lame_4_not_providing_my_own_sample_dataframe@lameduck.com 1 4 62
1 1 bc add11 xyz@lameduck.com 2 5 16
2 2 def add111 wxyz@lamerduck.com 3 6 18
- 从技术上讲,这可以在不使用
enumerate 索引列表中的每个数据帧的情况下完成。
- 这适用于
lists 的数据帧,因为 df 是一个引用,因此当它在循环中更新时,list 中的正确数据帧也会更新。
- 我认为发生的事情不太明显,这就是我使用
enumerate 显示代码的原因。
for df in df_list:
df[newcolumns] = df[columns].applymap(len)
替代方案
备选方案 1
# zip the columns and new column name together
cols = list(zip(columns, newcolumns))
# iterate through list of dataframe
for i, df in enumerate(df_list):
# iterate through the column name pairs
for c in cols:
# create the columns using .str.len()
df_list[i][c[1]] = df[c[0]].str.len()
备选方案 2
for i, df in enumerate(df_list):
df_list[i][newcolumns] = df[columns].apply(lambda x: x.str.len())
%%timeit 测试
# sample dataframe with 99999 rows
d = pd.concat([df1]* 33333).reset_index(drop=True)
# functions to test
columns = ['name', 'address', 'email']
newcolumns = ['name_length', 'address_length', 'email_length']
cols = list(zip(columns, newcolumns))
def test1(df):
df[newcolumns] = df[columns].applymap(len)
return df
def test2(df):
for c in cols:
df[c[1]] = df[c[0]].str.len()
return df
def test3(df):
df[newcolumns] = df[columns].apply(lambda x: x.str.len())
return df
# tests
%%timeit
test1(d)
[out]:
67.6 ms ± 1.56 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%%timeit
test2(d)
[out]:
87.6 ms ± 2.26 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%%timeit
test3(d)
[out]:
89.4 ms ± 543 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)