Python 如何通过从另一个更大的数据帧中选择一些数据列表来高效地构建熊猫数据帧(或dict)?
我需要创建一个数据框或字典。如果Python 如何通过从另一个更大的数据帧中选择一些数据列表来高效地构建熊猫数据帧(或dict)?,python,python-3.x,pandas,numpy,dataframe,Python,Python 3.x,Pandas,Numpy,Dataframe,我需要创建一个数据框或字典。如果N=3(其他列表中的列表数量),预期输出如下: d = { 'xs0': [[7.0, 986.0], [17.0, 6.0], [7.0, 67.0]], 'ys0': [[79.0, 69.0], [179.0, 169.0], [729.0, 69.0]], 'xs1': [[17.0, 166.0], [17.0, 116.0], [17.0, 126.0]], 'ys1': [[179.0, 169.0], [179.0,
N=3
(其他列表中的列表数量),预期输出如下:
d = {
'xs0': [[7.0, 986.0], [17.0, 6.0], [7.0, 67.0]],
'ys0': [[79.0, 69.0], [179.0, 169.0], [729.0, 69.0]],
'xs1': [[17.0, 166.0], [17.0, 116.0], [17.0, 126.0]],
'ys1': [[179.0, 169.0], [179.0, 1169.0], [1729.0, 169.0]],
'xs2': [[27.0, 276.0], [27.0, 216.0], [27.0, 226.0]],
'ys2': [[279.0, 269.0], [279.0, 2619.0], [2579.0, 2569.0]]
}
为此,我编写了以下代码。但我需要这段代码运行得更快:
import numpy as np
import pandas as pd
df_dict = {
'X1': [1, 2, 3, 4, 5, 6, 7, 8, np.nan],
'Y1': [9, 29, 39, 49, np.nan, 69, 79, 89, 99],
'X2': [11, 12, 13, 14, 15, 16, 17, 18, np.nan],
'Y2': [119, 129, 139, 149, np.nan, 169, 179, 189, 199],
'X3': [21, 22, 23, 24, 25, 26, 27, 28, np.nan],
'Y3': [219, 229, 239, 249, np.nan, 269, 279, 289, 299],
'S': [123, 11, 123, 11, 123, 123, 123, 35, 123],
'C': [9, 8, 7, 6, 5, 4, 3, 2, 1],
'F': [1, 1, 1, 1, 2, 3, 3, 3, 3],
'OTHER': [10, 20, 30, 40, 50, 60, 70, 80, 90],
}
bigger_df = pd.DataFrame(df_dict)
plots = [
{ 'x': 'X1', 'y': 'Y1', },
{ 'x': 'X2', 'y': 'Y2', },
{ 'x': 'X3', 'y': 'Y3', }
]
N = 3
d = {}
s_list = [123, 145, 35]
n = 0
for p in plots:
# INITIALIZATES THE DICTIONARY ELEMENTS
d['xs{}'.format(n)] = [[] for x in range(N)]
d['ys{}'.format(n)] = [[] for x in range(N)]
# BUILDS THE LISTS FOR THOSE ELEMENTS
for index in range(3):
df = bigger_df.filter([p['x'], p['y'], 'S', 'F', 'C']) # selects the minimum of columns needed
df = df[df['F'].isin([2, 3, 4, 9]) & df[p['x']].notnull() & df[p['y']].notnull() & (df.S == s_list[index])]
df.sort_values(['C'], ascending=[True], inplace=True)
d['xs{}'.format(n)][index] = list(df[p['x']])
d['ys{}'.format(n)][index] = list(df[p['y']])
n += 1
print(d)
我想知道,我是否可以用熊猫或裸体做些小把戏,而不是在一个循环上建立字典。如果结果是一个数据帧而不是一个字典,对我来说也是好的,甚至更好,但我不知道它是否会更有效
一些想法?根据您的输入和预期输出(每个键的列表中相同值的三倍?),至少您可以通过以下方式替换绘图中p的
:
for p in plots:
# Select the data you want
df = bigger_df.filter([p['x'], p['y'], 'S', 'F', 'C']) # selects the minimum of columns needed
df = df[df['F'].isin([2, 3, 4, 9]) & df[p['x']].notnull() & df[p['y']].notnull() & (df.S == 123)] # I have used 123 to simplify, actually the value is an integer variable
df.sort_values(['C'], ascending=[True], inplace=True)
# fill the dictionary
d['xs{}'.format(n)] = [list(df[p['x']]) for x in range(N)]
d['ys{}'.format(n)] = [list(df[p['y']]) for x in range(N)]
n += 1
至少您将保存为范围(3)
中的索引,并在较大的df上执行相同的操作3次。使用timeit
我的代码从210毫秒下降到70.5毫秒(大约三分之一)
编辑:以您重新定义问题的方式,我认为这可能会完成您想要的工作:
# put this code after the definition of plots
s_list = [123, 145, 35]
# create an empty DF to add your results in the loop
df_output = pd.DataFrame(index=s_list, columns=['xs0','ys0', 'xs1', 'ys1', 'xs2', 'ys2'])
n = 0
for p in plots:
# Select the data you want and sort them on the same line
df_p = bigger_df[bigger_df['F'].isin([2, 3, 4, 9]) & bigger_df[p['x']].notnull() & bigger_df[p['y']].notnull() & bigger_df['S'].isin(s_list)].sort_values(['C'], ascending=[True])
# on bigger df I would do a bit differently if the isin on F and S are the same for the three plots,
# I would create a df_select_FS outside of the loop before (might be faster)
# Now, you can do groupby on S and then you create a list of element in column p['x'] (and same for p['y'])
# and you add them in you empty df_output in the right column
df_output['xs{}'.format(n)] = df_p.groupby('S').apply(lambda x: list(x[p['x']]))
df_output['ys{}'.format(n)] = df_p.groupby('S').apply(lambda x: list(x[p['y']]))
n += 1
两个注意事项:首先,如果在s_列表中有两倍相同的值,它可能无法按您希望的方式工作;其次,如果不满足条件(如s
中的示例145),则在df_输出中有nan
,您的代码根本无法运行,您期望的输出是什么?是的,我知道。我不想给这个问题增添更多的噪音。我会在几分钟内让它为你运行minutes@cᴏʟᴅsᴘᴇᴇᴅ 它现在运行。很抱歉,我在评论中写道“我已经使用了文字123来简化示例”。事实上,我在实际应用程序中使用了一个变量,因此结果列表永远不会重复,我将修改问题中的预期输出,以避免混淆。谢谢你的观点。也许你可以在我的回答中使用类似于df.S.isin(S_列表)
的条件,看看df的行为,然后对S值使用groupby
。我不太清楚,有可能的话我会试试的@ChesuCR如果我很好地理解了你的问题,请查看我的编辑是的,的确,“F和S对于三个图是相同的”。所以我应用了你所有的建议,时间从150-170ms下降到50-70ms。快了将近3倍!!我感谢你的回答和努力:)这样更快,希望足够好。另外,如果要通过空列表删除所有nan
,可以执行df\u输出[df\u输出.isnull()]=df\u输出[df\u输出.isnull()].applymap(lambda x:[])