【问题标题】:How do I efficiently change a pd.Series of lists in a dataframe to a pd.Series of np.arrays如何有效地将数据框中的 pd.Series 列表更改为 np.arrays 的 pd.Series
【发布时间】:2019-03-05 20:43:18
【问题描述】:

我有一个 PostgreSQL 数据库,其数据类似于: 日期,字符变化,字符变化,整数[] 在整数数组列中存储值列表:1,2,3,4,5 我正在使用 pd.read_sql 将数据读入数据帧。

所以我有一个数据框,其中包含一个日期列、几个字符串列,然后是一个包含整数列表的列。

数组值经常在 numpy 数组中用于向量数学运算。

在过去,我找不到将列表列转换为 numpy 数组列的方法,而无需逐行循环和重新创建数据帧。 举个例子:

import pandas as pd
import numpy as np

col1 = ['String data'] * 4
col2 = [[1,2,3,4,5]] * 4
d = {'Description': col1, 'Measures':col2}
df = pd.DataFrame(d)

new_df = pd.DataFrame(columns=df.columns)

for i in range(len(df)):
    new_df.loc[i, ['Description','Measures']] = [df.at[i,'Description'], np.array(df.at[i,'Measures'])]

print(new_df)

这个循环可能超过几千行。

最近我发现如果我可以对 Series -> list -> nparray -> list -> Series 进行单行转换并更有效地实现结果。

import pandas as pd
import numpy as np

col1 = ['String data'] * 4
col2 = [[1,2,3,4,5]] * 4
d = {'Description': col1, 'Measures':col2}
df = pd.DataFrame(d)

df['NParray'] = pd.Series(list(np.array(list(np.array(df['Measures'])))))
df.drop(['Measures'], axis=1, inplace=True)

print(df)
print(type(df['NParray'][0]))

我阅读并尝试使用 Series.array 和 Series.to_numpy,但它们并没有真正实现我想要做的事情。

所以,问题是: 有没有一种方法可以将 pd.Series 列表转换为 numpy 数组,就像我尝试做的那样? 有没有更简单的方法可以将这些列表批量转换为 numpy 数组?

我希望像这样简单的东西:

df['NParray'] =np.asarray(df['Measures'])
df['NParray'] =np.array(df['Measures'])
df['NParray'] =df['Measures'].array
df['NParray'] =df['Measures'].to_numpy()

但是这些有不同的功能,不适合我的目的。

------------测试后编辑-------------------------------- ----------------

我设置了一个小测试,看看时间和效率会有什么不同:

import pandas as pd
import numpy as np

def get_dataframe():
    col1 = ['String data'] * 10000
    col2 = [list(range(0,5000))] * 10000
    d = {'Description': col1, 'Measures':col2}
    df = pd.DataFrame(d)
    return(df)


def old_looping(df):
    new_df = pd.DataFrame(columns=df.columns)
    starttime = pd.datetime.now()
    for i in range(len(df)):
        new_df.loc[i, ['Description','Measures']] = [df.at[i,'Description'], np.array(df.at[i,'Measures'])]
    endtime = pd.datetime.now()
    duration = endtime - starttime
    print('Looping', duration)


def series_transforms(df):
    starttime = pd.datetime.now()
    df['NParray'] = pd.Series(list(np.array(list(np.array(df['Measures'])))))
    df.drop(['Measures'], axis=1, inplace=True)
    endtime = pd.datetime.now()
    duration = endtime - starttime
    print('Transforms', duration)


def use_apply(df):
    starttime = pd.datetime.now()
    df['Measures'] = df['Measures'].apply(np.array)
    endtime = pd.datetime.now()
    duration = endtime - starttime
    print('Apply', duration)


def run_test(tests):
    for i in range(tests):
        construct_df = get_dataframe()
        old_looping(construct_df)
    for i in range(tests):
        construct_df = get_dataframe()
        series_transforms(construct_df)
    for i in range(tests):
        construct_df = get_dataframe()
        use_apply(construct_df)

run_test(5)

10,000 行的结果是: 转换 3.945816
转换 3.968821
转换 3.891866
转换 3.859437
转换 3.860590

申请 4.218867
申请 4.015742
申请 4.046986
申请 3.906360 申请 3.890740

循环 27.662418
循环 27.814523
循环 27.298895
循环 27.565626
循环 27.222970

通过 Series-List-NP Array-List-Series 转换比使用 Apply 快得可以忽略不计。 Apply 绝对是更短的代码并且可能更容易理解。

增加行数或数组长度会增加同样数量的次数。

【问题讨论】:

    标签: python pandas numpy series


    【解决方案1】:

    最简单的方法可能是使用 apply 来转换为 np.array:df['Measures'].apply(np.array)

    完整示例:

    import pandas as pd
    import numpy as np
    
    col1 = ['String data'] * 4
    col2 = [[1,2,3,4,5]] * 4
    d = {'Description': col1, 'Measures':col2}
    df = pd.DataFrame(d)
    display(df.Measures)
    
    df['NParray'] = df['Measures'].apply(np.array)
    df.drop(['Measures'], axis=1, inplace=True)
    
    print(df)
    print(type(df['NParray'][0]))
    

    【讨论】:

    • 如此简单。我完全忘记了尝试使用 apply()。有了这个,我什至不必创建新列然后删除旧列,我可以简单地执行 df['Measures'] = df['Measures'].apply(np.array) 感谢您的快速和简单的答案。还在学习中。
    • 实际上,我刚刚读到 apply 可能不是一个好主意。 stackoverflow.com/questions/54432583/… 尤其是 pd.Series。我将不得不运行一些大容量测试,看看我是否需要坚持 df['NParray'] = pd.Series(list(np.array(list(np.array(df['Measures']))) ))
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-23
    • 2021-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    相关资源
    最近更新 更多