Reputation: 13
I am using multiprocessing in python to improve the performance of the code. Instead of appending the result directly in a dataframe, I am using a common list.
df_list = mp.Manager().list()
The values are calculated and appended in the above list by different processes.
lock.acquire()
try:
temp = [a, b, c, d, e, f, g, h, i, j, k, l, m, n]
df_list.append(temp)
finally:
lock.release()
The alphabets are variables containing different values.
Once the child processes terminate, the list contains the following values:
print(df_list)
[[0, '2009-10-01', '2010-01-01', 3, 3, 1, 0.25, 0.9, 6, 100000, 101866.70524177742, 7.68, 100000, 0.0],
[1, '2009-10-01', '2010-01-01', 5, 7, 2, 0.25, 0.4, 8, 100000, 101866.70524177742, 9.32, 100000, 0.0]]
Now, I need to convert the list to dataframe.
cols = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N"]
df = pd.DataFrame(df_list, columns = cols)
However, I get the following error:
ValueError Traceback (most recent call last)
~\Desktop\Temp\Python\calculate.py in <module>
469 print(df_list)
470
--> 471 df = pd.DataFrame(df_list, columns = cols)
472
~\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\frame.py in __init__(self, data, index, columns, dtype, copy)
466 dtype=values.dtype, copy=False)
467 else:
--> 468 raise ValueError('DataFrame constructor not properly called!')
469
470 NDFrame.__init__(self, mgr, fastpath=True)
Could you please let me know if I am doing anything wrong.
EDIT: If we replace the list with standard list it works (as mentioned in the comments as well). However, in multiprocessing we need a manager list to share across the processes.
Also, I found a workaround and it seems to work:
simple_list = []
for l in df_list:
simple_list.append(l)
df = pd.DataFrame(simple_list, columns = cols)
However, as you can see not a very elegant way of doing things. Still, the question persists - Why can't I convert the manager list to dataframe in a single step. May be I am doing something wrong?
Upvotes: 1
Views: 898
Reputation: 43553
It works fine here (when I use a standard list
):
In [1]: import pandas as pd
In [2]: df_list = [[0, '2009-10-01', '2010-01-01', 3, 3, 1, 0.25, 0.9, 6, 100000, 101866.70524177742, 7.6
...: 8, 100000, 0.0],
...: [1, '2009-10-01', '2010-01-01', 5, 7, 2, 0.25, 0.4, 8, 100000, 101866.70524177742, 9.32, 100000,
...: 0.0]]
In [3]: cols = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N"]
In [4]: df = pd.DataFrame(df_list, columns = cols)
Out[4]:
A B C D E F G H I J K L M N
0 0 2009-10-01 2010-01-01 3 3 1 0.25 0.9 6 100000 101866.705242 7.68 100000 0.0
1 1 2009-10-01 2010-01-01 5 7 2 0.25 0.4 8 100000 101866.705242 9.32 100000 0.0
So the problem lies with using a proxy. The solution then is to convert it to a list before using it to create a DataFrame
. Observe:
In [1]: import multiprocessing as mp
In [2]: proxy = mp.Manager().list([1,2,3])
Out[2]: <ListProxy object, typeid 'list' at 0x8042e5710>
In [3]: reallist = list(proxy)
Out[3]: [1, 2, 3]
In [4]: type(reallist)
Out[4]: list
After the explicit conversion, we're back to a regular old list.
Upvotes: 1
Reputation: 824
I know the below approach for correct conversion from list to Dataframe (there might be many more approaches):
df_list= [[ {"A":0 }, {"B": '2009-10-01'}],
[ {"A":1}, {"B":'2009-10-01'}]]
df = pd.DataFrame(df_list)
Upvotes: 0