Фильтрация вложенного списка - PullRequest
0 голосов
/ 19 ноября 2018

У меня есть вложенный список, как показано ниже: -

 list = [['A:1','B:(null)','C:3','D:4'],
        ['A:1','B:abc','C:6','D:7'],
        ['A:1','B:def','C:2','G:44','E: 600','F: 6600'],
        ['A:1','B:ghi','C:33','D:44']]

Я хочу преобразовать его в фрейм данных таким образом, чтобы все, что before : было бы column name и after : было бызначение

Здесь у меня есть два типа данных, один из которых: -

[['A:1','B:(null)','C:3','D:4'],
  ['A:1','B:abc','C:6','D:7'],
  ['A:1','B:ghi','C:33','D:44']]

, и один элемент отличается,

['A:1','B:def','C:2','G:44','E: 600','F: 6600']

Ожидаемый результат: -

df1 =

enter image description here

и df2 =

enter image description here

Q.1) На данный момент у меня есть только два вида данных, поэтому я хочу два фрейма данных.Q.2) можем ли мы сделать это динамическим, чтобы он создавал несколько DFS в соответствии с элементами в списке.

Ответы [ 2 ]

0 голосов
/ 19 ноября 2018

Вы можете:

  1. создать диктовку из вашего списка (я решил заменить "(null)" на None)
  2. группа dict с по отсортированным ключам через collections.defaultdict
  3. создание и выдача фреймов данных из групп

from collections import defaultdict
import pandas as pd

# convert to dictionaries        
def makeDict(inner): 
    return {k: (v if v!= "(null)" else None) for k,v in (p.split(":") for p in inner)}

# group and yield dfs
def makeIt(l):
    # collect data as dicts
    dicts = []
    for inner in l:
        dicts.append( makeDict(inner))

    # group by sorted keys
    t = defaultdict(list)
    for d in dicts:
        t[tuple(sorted(d.keys()))].append(d)

    # create dataframes from groups and yield them
    for k in t:
        df = pd.DataFrame(t[k])
        yield df

Использование:

l = [['A:1','B:(null)','C:3','D:4'],
     ['A:1','B:abc','C:6','D:7'],
     ['A:1','B:def','C:2','G:44','E: 600','F: 6600'],
     ['A:1','B:ghi','C:33','D:44']]

dfs = list(makeIt(l))

for df in dfs:
    print("-"*20)
    print(df)

Выход:

--------------------
   A     B   C   D
0  1  None   3   4
1  1   abc   6   7
2  1   ghi  33  44

--------------------
   A    B  C     E      F   G
0  1  def  2   600   6600  44
0 голосов
/ 19 ноября 2018

IIUC, 1-й конвертируйте ваш list в list из dict (также не называйте ваш список как список, он перезапишет функцию python), 2-й создайте фрейм данных, используя isnull с dotсоздайте ключ группы, затем создайте dict, я не рекомендую динамически создавать фреймы данных, вы можете поместить их в dict, если это важно, посмотрите на local

[dict(tuple(y.split(":")) for y in x )for x in l] # make you list to list of dict 
Out[11]: 
[{'A': '1', 'B': '(null)', 'C': '3', 'D': '4'},
 {'A': '1', 'B': 'abc', 'C': '6', 'D': '7'},
 {'A': '1', 'B': 'def', 'C': '2', 'E': ' 600', 'F': ' 6600', 'G': '44'},
 {'A': '1', 'B': 'ghi', 'C': '33', 'D': '44'}]
newl=[dict(tuple(y.split(":")) for y in x )for x in l]
pd.DataFrame(newl)
Out[13]: 
   A       B   C    D     E      F    G
0  1  (null)   3    4   NaN    NaN  NaN
1  1     abc   6    7   NaN    NaN  NaN
2  1     def   2  NaN   600   6600   44
3  1     ghi  33   44   NaN    NaN  NaN
newdf=pd.DataFrame(newl)
s=newdf.isnull().dot(newdf.columns)# using dot create the groupby key 
s
Out[16]: 
0    EFG
1    EFG
2      D
3    EFG
dtype: object

{x: y for x , y  in newdf.groupby(s)}# using group by create the dict 
Out[17]: 
{'D':    A    B  C    D     E      F   G
 2  1  def  2  NaN   600   6600  44, 'EFG':    A       B   C   D    E    F    G
 0  1  (null)   3   4  NaN  NaN  NaN
 1  1     abc   6   7  NaN  NaN  NaN
 3  1     ghi  33  44  NaN  NaN  NaN}
d={x: y for x , y  in newdf.groupby(s)}
d['D'].dropna(1,thresh=1)
# result can using dict selection
# dropna here means atleast one column should have at least one not null value , 
# if it is all null , then we drop the entire columns  
Out[19]: 
   A    B  C    E      F   G
2  1  def  2  600   6600  44

d['EFG'].dropna(1,thresh=1)
Out[21]: 
   A       B   C   D
0  1  (null)   3   4
1  1     abc   6   7
3  1     ghi  33  44

Не рекомендуется local

d={x: y.dropna(1,thresh=1) for x , y  in newdf.groupby(s)}
variables = locals()
for i,j in enumerate(d.values()):
    variables["df{0}".format(i+1)] = j
df1
Out[26]: 
   A    B  C     E      F   G
2  1  def  2   600   6600  44
df2
Out[27]: 
   A       B   C   D
0  1  (null)   3   4
1  1     abc   6   7
3  1     ghi  33  44
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...