如何有效地将数据框中的列表的pd.Series更改为np.arrays的pd.Series

时间:2019-03-05 20:43:19

标签: python pandas numpy series

我有一个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

通过“序列-列表-NP”数组-“列表-系列”的转换比使用“应用”要快得多。 Apply绝对是较短的代码,可能更容易理解。

增加行数或数组长度将使次数增加相同的幅度。

1 个答案:

答案 0 :(得分:2)

最简单的方法是将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]))