Панды: разделите столбец, содержащий точку с запятой, на несколько столбцов на основе значений - PullRequest
4 голосов
/ 13 мая 2019

Мои данные в ddata.csv выглядят следующим образом:

col1,col2,col3,col4
A,10,a;b;c, 20
B,30,d;a;b,40
C,50,g;h;a,60

Я хочу разделить col3 на несколько столбцов, но на основе их значений. В других случаях я хотел бы, чтобы мои окончательные данные выглядели как

col1, col2, name_a, name_b, name_c, name_d, name_g, name_h, col4
A,    10,   a,      b,      c,      NULL,   NULL,   NULL,   20
B,    30,   a,      b,      NULL,   d,      NULL,   NULL,   40
C,    50,   a,      NULL,   NULL,   NULL,   g,      h,      60

Мой код, на данный момент взятый из этого ответа , является неполным:

import pandas as pd

import string
L = list(string.ascii_lowercase)

names = dict(zip(range(len(L)), ['name_' + x for x in  L]))
df = pd.read_csv('ddata.csv')
df2 = df['col3'].str.split(';', expand=True).rename(columns=names)

Имена столбцов «a», «b», «c» ... взяты случайным образом и не имеют отношения к фактическим данным a, b, c.

Прямо сейчас мой код может просто разбить 'col3' на три столбца следующим образом:

name_a name_b name_c
a      b      c
d      e      f
g      h      i

Но, это должно быть как name_a, name_b, name_c, name_d, name_g, name_h a, b, c, NULL, NULL, NULL a, b, NULL, d, NULL, NULL а, NULL, NULL, NULL, г, ч

и в конце мне нужно просто заменить col3 на эти несколько столбцов.

Ответы [ 2 ]

5 голосов
/ 13 мая 2019

Использование Series.str.get_dummies:

print (df['col3'].str.get_dummies(';'))
   a  b  c  d  g  h
0  1  1  1  0  0  0
1  1  1  0  1  0  0
2  1  0  0  0  1  1

Для извлечения столбца col3 из исходного использования DataFrame.pop, создайте новый DataFrame с несколькими значениями по именам столбцов в numpy, замените NaN s вместо пустых строк на DataFrame.where и DataFrame.add_prefix для имен новых столбцов.

pos = df.columns.get_loc('col3')

df2 = df.pop('col3').str.get_dummies(';').astype(bool)
df2 = (pd.DataFrame(df2.values * df2.columns.values[ None, :], 
                    columns=df2.columns,
                    index=df2.index)
         .where(df2)
         .add_prefix('name_'))

Последнее объединение всех фреймов данных, отфильтрованных по позициям с iloc объединение по concat:

df = pd.concat([df.iloc[:, :pos], df2, df.iloc[:, pos:]], axis=1)
print (df)
  col1  col2 name_a name_b name_c name_d name_g name_h  col4
0    A    10      a      b      c    NaN    NaN    NaN    20
1    B    30      a      b    NaN      d    NaN    NaN    40
2    C    50      a    NaN    NaN    NaN      g      h    60
0 голосов
/ 13 мая 2019

@ Jezrael решение отлично.Я не знал str.get_dummies до сих пор.

Я придумаю решение, используя stack, pivot_table, np.where и pd.concat

df1 = df.col3.str.split(';', expand=True).stack().reset_index(level=0)
df2 = pd.pivot_table(df1, index='level_0', columns=df1[0], aggfunc=len)

Out[1658]:
0          a    b    c    d    g    h
level_0
0        1.0  1.0  1.0  NaN  NaN  NaN
1        1.0  1.0  NaN  1.0  NaN  NaN
2        1.0  NaN  NaN  NaN  1.0  1.0

Далее, заполните 1.0 именами столбцов, используя np.where,найти индекс col3 и использовать pd.concat для построения окончательного df

df2[:] = np.where(df2.isna(), np.nan, df2.columns)
i = df.columns.tolist().index('col3')
pd.concat([df.iloc[:,:i], df2.add_prefix('name_'), df.iloc[:,i+1:]], axis=1)

Out[1667]:
  col1  col2 name_a name_b name_c name_d name_g name_h  col4
0    A    10      a      b      c    NaN    NaN    NaN    20
1    B    30      a      b    NaN      d    NaN    NaN    40
2    C    50      a    NaN    NaN    NaN      g      h    60
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...