Простой фрейм данных, как показано ниже, и я хочу напечатать строки одного и того же индекса в 1 отсортированной строке.
В розыске:
123@1st line; 2nd line; 3rd line; 4th line
456@a1st line; a2nd line; a3rd line
Я пробовал:
import pandas as pd
from io import StringIO
csvfile = StringIO(
"""Group Sort String
123 207 1st line
123 208 2nd line
123 209 3rd line
123 210 4th line
456 625 a1st line
456 626 a2nd line
456 627 a3rd line""")
df = pd.read_csv(csvfile, sep = '\t', engine='python')
df['Group'] = df['Group'].astype(str)
df['Sort'] = df['Sort'].astype(int)
df = df.sort_values(['Sort'], ascending=[True])
df_1 = df.groupby(['Group'])['String'].apply(lambda x: '; '.join(x.astype(str))).reset_index()
df_1['String'] = df_1['String'].str.split('; ').apply(set).str.join('; ')
for index, row in df_1.iterrows():
print(row['Group'] + '@' + row['String'])
Но вывод:
123@3rd line; 4th line; 1st line; 2nd line
456@a3rd line; a2nd line; a1st line
Где пошло не так и как я могу это исправить? Спасибо.
Проблема в том, что ваши данные плохо отформатированы.
Либо вы сохраняете \t в качестве разделителя (то, что вы сделали в заголовке), либо добавляете \t между каждым из ваших столбцов, либо вы меняете разделитель как "" (то, что вы сделали в теле вашего фрейма данных).
Использование обоих приведет к ненужным проблемам форматирования:
csvfile = StringIO(
"""Group Sort String
123 207 1st_line
123 208 2nd_line
123 209 3rd_line
123 210 4th_line
456 625 a1st_line
456 626 a2nd_line
456 627 a3rd_line""")
df = pd.read_csv(csvfile, header = 0, sep = ' ', engine='python')
csvfile = StringIO(
"""Group\tSort\tString
123\t207\t1st line
123\t208\t2nd line
123\t209\t3rd line
123\t210\t4th line
456\t625\ta1st line
456\t626\ta2nd line
456\t627\ta3rd line""")
df = pd.read_csv(csvfile, header = 0, sep = "\t", engine='python')
После этой операции вы можете проверить с помощью отладчика, например, ваш вновь созданный фрейм данных в виде трех столбцов, чего не было в вашем предыдущем коде.
Затем, чтобы напечатать все значения «String», использующие одно и то же значение «Group», используйте группа по.
df.groupby("Group").groups
Out[21]: {123: [0, 1, 2, 3], 456: [4, 5, 6]}
Или для лучшей визуализации:
for name, group in df.groupby("Group"):
print(f"{name} : {group.loc[:, 'String'].to_numpy()}\n")
123 : ['1st line' '2nd line' '3rd line' '4th line']
456 : ['a1st line' 'a2nd line' 'a3rd line']
Следуя вашим рекомендациям:
for name, group in df.groupby("Group"):
print(f"{name}@{'; '.join(group.loc[:, 'String'].to_numpy())}\n")
123@1st line; 2nd line; 3rd line; 4th line
456@a1st line; a2nd line; a3rd line
проблема с set
в
df_1['String'] = df_1['String'].str.split('; ').apply(set).str.join('; ')
потому что наборы неупорядочены. Поэтому вам нужно заменить его чем-то вроде
df = df.drop_duplicates(subset=['String'])
в начале