Преобразование фрейма данных - PullRequest
0 голосов
/ 31 августа 2018

Я хотел бы эффективно преобразовать фрейм данных, используя следующую логику:

Для каждого столбца фрейма данных я идентифицирую уникальные вхождения, которые появляются в этом конкретном столбце. Скажем, что для столбца i существует n_i уникальных таких случаев. Затем каждому из этих вхождений я назначаю уникальный список с n_i-компонентами, так что этот список имеет нули везде, кроме одной позиции, соответствующей выбранному уникальному вхождению. Делая это для каждого столбца, я буду однозначно идентифицировать каждый элемент во фрейме данных с помощью списка списков. Пример может оказаться гораздо более удобным, чтобы объяснить, чего я хочу.

Возьмите следующий фрейм данных:

data = { 'name': ['Alarm1','Alarm2','Alarm2','Alarm3','Alarm4'],
    'severity':[1,2,3,4,4],
    'domain':['RAN','TRX','RAN','RAN','TRX']}
df=pd.DataFrame(data, index = [1,2,3,4,5])

Затем я хотел бы преобразовать этот фрейм данных в массив с массивами данных, похожий на вывод:

[[1, 0, 0, 0], [1, 0, 0, 0], [1, 0]]
[[0, 1, 0, 0], [0, 1, 0, 0], [0, 1]]
[[0, 1, 0, 0], [0, 0, 1, 0], [1, 0]]
[[0, 0, 1, 0], [0, 0, 0, 1], [1, 0]]
[[0, 0, 0, 1], [0, 0, 0, 1], [0, 1]]

Мой код для вышеуказанного преобразования следующий:

l0=[((df.name.unique()==df.iloc[0][0])*1).tolist(),((df.severity.unique()==df.iloc[0][1])*1).tolist()]
l0.append(((df.domain.unique()==df.iloc[0][2])*1).tolist())
l1=[((df.name.unique()==df.iloc[1][0])*1).tolist(),((df.severity.unique()==df.iloc[1][1])*1).tolist()]
l1.append(((df.domain.unique()==df.iloc[1][2])*1).tolist())
l2=[((df.name.unique()==df.iloc[2][0])*1).tolist(),((df.severity.unique()==df.iloc[2][1])*1).tolist()]
l2.append(((df.domain.unique()==df.iloc[2][2])*1).tolist())
l3=[((df.name.unique()==df.iloc[3][0])*1).tolist(),((df.severity.unique()==df.iloc[3][1])*1).tolist()]
l3.append(((df.domain.unique()==df.iloc[3][2])*1).tolist())
l4=[((df.name.unique()==df.iloc[4][0])*1).tolist(),((df.severity.unique()==df.iloc[4][1])*1).tolist()]
l4.append(((df.domain.unique()==df.iloc[4][2])*1).tolist())

После этого я просто печатаю все списки l0, .., l4, чтобы получить вывод. Конечно, это крайне неэффективно, так как я создаю каждый из этих списков вручную. Я хотел бы выполнить итерацию, чтобы построить их все сразу, а также выполнить итерацию для части column.unique для каждого столбца во фрейме данных для каждого из списков.

Я был бы очень признателен, если бы кто-то мог оказать некоторую помощь или совет. Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 31 августа 2018

Вам может понадобиться pd.get_dummies:

import pandas as pd

data = {
    'name': ['Alarm1','Alarm2','Alarm2','Alarm3','Alarm4'],
    'severity': [1,2,3,4,4],
    'domain': ['RAN','TRX','RAN','RAN','TRX']}

df = pd.DataFrame(data, index=[1,2,3,4,5])
df = df.astype(str)

df2 = pd.get_dummies(df)

out = list(zip(*[df2[[x for x in df2.columns if x.startswith(key)]].values.tolist() for key in data.keys()]))
print(out)

# Output
# [([1, 0, 0, 0], [1, 0, 0, 0], [1, 0]), 
#  ([0, 1, 0, 0], [0, 1, 0, 0], [0, 1]), 
#  ([0, 1, 0, 0], [0, 0, 1, 0], [1, 0]), 
#  ([0, 0, 1, 0], [0, 0, 0, 1], [1, 0]), 
#  ([0, 0, 0, 1], [0, 0, 0, 1], [0, 1])]
0 голосов
/ 31 августа 2018

Я думаю, что нужно get_dummies работать со значениями строк, поэтому сначала используется astype:

df1 = pd.get_dummies(df.astype(str))
print (df1)
   name_Alarm1  name_Alarm2  name_Alarm3  name_Alarm4  severity_1  severity_2  \
1            1            0            0            0           1           0   
2            0            1            0            0           0           1   
3            0            1            0            0           0           0   
4            0            0            1            0           0           0   
5            0            0            0            1           0           0   

   severity_3  severity_4  domain_RAN  domain_TRX  
1           0           0           1           0  
2           0           0           0           1  
3           1           0           1           0  
4           0           1           1           0  
5           0           1           0           1  

Тогда, если нужны списки, используйте groupby по первому значению перед _ для списка кортежей:

L = list(zip(*[x.values.tolist() for _, x in df1.groupby(lambda x: x.split('_')[0], axis=1)]))
print (L)

[([1, 0], [1, 0, 0, 0], [1, 0, 0, 0]), 
 ([0, 1], [0, 1, 0, 0], [0, 1, 0, 0]), 
 ([1, 0], [0, 1, 0, 0], [0, 0, 1, 0]), 
 ([1, 0], [0, 0, 1, 0], [0, 0, 0, 1]), 
 ([0, 1], [0, 0, 0, 1], [0, 0, 0, 1])]

Или создать MultiIndex в столбцах с split:

df1.columns = df1.columns.str.split('_', expand=True)
print (df1)
    name                      severity          domain    
  Alarm1 Alarm2 Alarm3 Alarm4        1  2  3  4    RAN TRX
1      1      0      0      0        1  0  0  0      1   0
2      0      1      0      0        0  1  0  0      0   1
3      0      1      0      0        0  0  1  0      1   0
4      0      0      1      0        0  0  0  1      1   0
5      0      0      0      1        0  0  0  1      0   1
   Alarm1  Alarm2  Alarm3  Alarm4
1       1       0       0       0
2       0       1       0       0
3       0       1       0       0
4       0       0       1       0
5       0       0       0       1

Так что можно выбрать DataFrame по первому уровню:

print (df1['name'])
   Alarm1  Alarm2  Alarm3  Alarm4
1       1       0       0       0
2       0       1       0       0
3       0       1       0       0
4       0       0       1       0
5       0       0       0       1

print (df1['domain'])
   RAN  TRX
1    1    0
2    0    1
3    1    0
4    1    0
5    0    1

И при необходимости конвертировать в numpy array:

print (df1['name'].values)
[[1 0 0 0]
 [0 1 0 0]
 [0 1 0 0]
 [0 0 1 0]
 [0 0 0 1]]

print (df1['domain'].values)
[[1 0]
 [0 1]
 [1 0]
 [1 0]
 [0 1]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...