【问题标题】:How to add columns to all dataframes in a list如何将列添加到列表中的所有数据框
【发布时间】:2021-04-22 06:22:23
【问题描述】:

我有一个数据框列表,我想为每个数据框计算某些列的字符串值的长度,并使用这些计算值创建一个新列:

columns = ['name', 'address', 'email']
newcolumns = ['name_length', 'address_length', 'email_length']

代码:

def length(start, i, j):
    while i < len(columns):
        newcol = newcolumns[i]
        col = columns[j]
        df_list[start][newcol] = df_list[start][col].str.len()
        i += 1
        j += 1
    start += 1
    return df_list

可以像列表一样访问每个单独的数据框,即df[0]

我得到的结果只计算了第一个数据帧的名称和地址长度。其余数据帧未计算。

预期的结果是所有数据帧中的所有指定列都得到了计算结果。理想的答案是通过循环自动实现这一点,lambda。

如何修改我的代码?

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:
    • 为了更新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)
    

    【讨论】:

      猜你喜欢
      • 2017-03-03
      • 2022-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-29
      • 1970-01-01
      • 1970-01-01
      • 2019-06-23
      相关资源
      最近更新 更多