У мене є великий файл даних Pandas, де єкількість багатозначних стовпців. Ці стовпці мають "/" у своїх іменах, а значення в цих стовпцях також розділені "/". Нижче наведено мінімальний репрезентативний приклад такого кадру даних.
Name North / South East / West No1 / No2 / No3
0 ABC 0 / 1 0 / 0 10 / 3 / 6
1 XYZ 1 / 0 0 / 1 4 / 5 / 6
2 PQR 1 / 0 0 / 1 3 / 6 / 6
Я хотів би розділити колонки. Простим способом є створення нового стовпця, а потім ітерація по довжині індексу, заповнюючи його розбитою рядком вздовж кожного елемента. Але мені доведеться його жорстко зафіксувати для всіх багатозначних стовпців.
Чи є більш загальний спосіб зробити це? Можливо, скануйте через df.columns, якщо елемент містить "/" в ньому, запустіть іншу функцію, щоб розбити цей стовпець? Для наведеного вище кадру даних бажаний вихідний результат полягає в наступному.
Name North South East West No1 No2 No3
0 ABC 0 1 0 0 10 3 6
1 XYZ 1 0 0 1 4 5 6
2 PQR 1 0 0 1 3 6 6
Відповіді:
0 для відповіді № 1#get columns not contains / and set index
cols = df.columns[~df.columns.str.contains("/")].tolist()
df = df.set_index(cols)
print (df)
North / South East / West No1 / No2 / No3
Name
ABC 0 / 1 0 / 0 10 / 3 / 6
XYZ 1 / 0 0 / 1 4 / 5 / 6
PQR 1 / 0 0 / 1 3 / 6 / 6
#create new columns names
c = df.columns.to_series().str.split(" / ", expand=True).stack().values.tolist()
print (c)
["North", "South", "East", "West", "No1", "No2", "No3"]
#list comprehension with split to df and concat output
df = pd.concat([df[x].str.split(" / ", expand=True) for x in df], axis=1)
print (df)
0 1 0 1 0 1 2
Name
ABC 0 1 0 0 10 3 6
XYZ 1 0 0 1 4 5 6
PQR 1 0 0 1 3 6 6
#assign new columns names
df.columns = c
df = df.reset_index()
print (df)
Name North South East West No1 No2 No3
0 ABC 0 1 0 0 10 3 6
1 XYZ 1 0 0 1 4 5 6
2 PQR 1 0 0 1 3 6 6
Складання часу:
df = pd.concat([df]*1000).reset_index(drop=True)
print (df)
def f(df):
return pd.concat([s.str.split(" / ").apply(pd.Series, index=c.split(" / ")) for c, s in df.set_index("Name").iteritems()], axis=1).reset_index()
print (f(df))
def f1(df):
cols = df.columns[~df.columns.str.contains("/")].tolist()
df = df.set_index(cols)
c = df.columns.to_series().str.split(" / ", expand=True).stack().values.tolist()
df = pd.concat([df[x].str.split(" / ", expand=True) for x in df], axis=1)
df.columns = c
return df.reset_index()
print (f1(df))
In [142]: %timeit (f(df))
1 loop, best of 3: 2.6 s per loop
In [143]: %timeit (f1(df))
10 loops, best of 3: 27.5 ms per loop
1 для відповіді № 2
Ось один підхід
In [1417]: pd.concat([s.str.split(" / ").apply(pd.Series, index=c.split(" / "))
for c, s in df.set_index("Name").iteritems()],
axis=1).reset_index()
Out[1417]:
Name North South East West No1 No2 No3
0 ABC 0 1 0 0 10 3 6
1 XYZ 1 0 0 1 4 5 6
2 PQR 1 0 0 1 3 6 6