У меня очень большой массив данных с 1000 столбцами. Первые несколько столбцов появляются только один раз, обозначая клиента. Следующие несколько столбцов представляют несколько встреч с клиентом, подчеркивание и число встреч. Каждое дополнительное столкновение добавляет новый столбец, поэтому количество столбцов НЕ фиксированное - оно будет расти со временем.

Пример структуры заголовка кадра данных:

id    dob    gender    pro_1    pro_10   pro_11   pro_2 ... pro_9    pre_1   pre_10   ...

Я пытаюсь изменить порядок столбцов на основе номера после имени столбца, поэтому все _1 должны быть вместе, все _2 должны быть вместе, и т. Д., Вот так:

id    dob    gender    pro_1    pre_1    que_1    fre_1    gen_1    pro2    pre_2    que_2    fre_2    ...

(Обратите внимание, что при переупорядочении следует правильно упорядочивать числа; текущий порядок обрабатывает их как строки, которые упорядочивают 1, 10, 11 и т. Д., А не 1, 2, 3)

Можно ли это сделать в пандах или я должен смотреть на что-то еще? Любая помощь будет принята с благодарностью! Спасибо!

РЕДАКТИРОВАТЬ:

В качестве альтернативы, можно ли переставить имена столбцов на основе строковой части И числовой части имен столбцов? Таким образом, результат будет выглядеть аналогично оригиналу, за исключением того, что числа будут считаться так, чтобы порядок был более интуитивным:

id    dob    gender    pro_1    pro_2    pro_3    ...    pre_1    pre_2    pre_3   ...

РЕДАКТИРОВАТЬ 2.0:

Просто хотел поблагодарить всех за помощь! Хотя сработал только один из ответов, я действительно ценю эти усилия и многое узнал о других подходах / способах обдумать это.

1
Chrestomanci 2 Май 2019 в 20:02

4 ответа

Лучший ответ

Вот один из способов, которым вы можете попробовать:

# column names copied from your example
example_cols = 'id    dob    gender    pro_1    pro_10   pro_11   pro_2  pro_9    pre_1   pre_10'.split()

# sample DF
df = pd.DataFrame([range(len(example_cols))], columns=example_cols)
df
#   id  dob  gender  pro_1  pro_10  pro_11  pro_2  pro_9  pre_1  pre_10
#0   0    1       2      3       4       5      6      7      8       9

# number of columns excluded from sorting
N = 3

# get a list of columns from the dataframe
cols = df.columns.tolist()

# split, create an tuple of (column_name, prefix, number) and sorted based on the 2nd and 3rd item of the tuple, then retrieved the first item.
# adjust "key = lambda x: x[2]" to group cols by numbers only
cols_new = cols[:N] + [ a[0] for a in sorted([ (c, p, int(n)) for c in cols[N:] for p,n in [c.split('_')]], key = lambda x: (x[1], x[2])) ]

# get the new dataframe based on the cols_new
df_new = df[cols_new]
#   id  dob  gender  pre_1  pre_10  pro_1  pro_2  pro_9  pro_10  pro_11
#0   0    1       2      8       9      3      6      7       4       5
1
jxc 2 Май 2019 в 18:30

К счастью, в Python есть один вкладыш, который может это исправить:

df = df.reindex(sorted(df.columns), axis=1)

Например, скажем, у вас был этот фрейм данных:

Импортировать панды как pd импортировать numpy как np

df = pd.DataFrame({'Name': [2, 4, 8, 0],
                   'ID': [2, 0, 0, 0],
                   'Prod3': [10, 2, 1, 8],
                   'Prod1': [2, 4, 8, 0],
                   'Prod_1': [2, 4, 8, 0],
                   'Pre7': [2, 0, 0, 0],
                   'Pre2': [10, 2, 1, 8],
                   'Pre_2': [10, 2, 1, 8],
                   'Pre_9': [10, 2, 1, 8]}
                   )

print(df)

Выход:

   Name  ID  Prod3  Prod1  Prod_1  Pre7  Pre2  Pre_2  Pre_9
0     2   2     10      2       2     2    10     10     10
1     4   0      2      4       4     0     2      2      2
2     8   0      1      8       8     0     1      1      1
3     0   0      8      0       0     0     8      8      8

Потом использовал

df = df.reindex(sorted(df.columns), axis=1)

Тогда датафрейм будет выглядеть так:

   ID  Name  Pre2  Pre7  Pre_2  Pre_9  Prod1  Prod3  Prod_1
0   2     2    10     2     10     10      2     10       2
1   0     4     2     0      2      2      4      2       4
2   0     8     1     0      1      1      8      1       8
3   0     0     8     0      8      8      0      8       0

Как вы можете видеть, столбцы без подчеркивания будут на первом месте, после чего следует порядок, основанный на числе после подчеркивания. Однако это также сортирует имена столбцов, поэтому имена столбцов, которые идут первыми в алфавите, будут первыми.

1
Edeki Okoh 2 Май 2019 в 17:58

Вам нужно разделить ваш столбец на '_', а затем преобразовать в int:

c = ['A_1','A_10','A_2','A_3','B_1','B_10','B_2','B_3']

df = pd.DataFrame(np.random.randint(0,100,(2,8)), columns = c)
df.reindex(sorted(df.columns, key = lambda x: int(x.split('_')[1])), axis=1)

Выход:

   A_1  B_1  A_2  B_2  A_3  B_3  A_10  B_10
0   68   11   59   69   37   68    76    17
1   19   37   52   54   23   93    85     3

В следующем случае вам потребуется сортировка людей:

import re
def atoi(text):
    return int(text) if text.isdigit() else text

def natural_keys(text):
    '''
    alist.sort(key=natural_keys) sorts in human order
    http://nedbatchelder.com/blog/200712/human_sorting.html
    (See Toothy's implementation in the comments)
    '''
    return [ atoi(c) for c in re.split(r'(\d+)', text) ]



df.reindex(sorted(df.columns, key = lambda x:natural_keys(x)), axis=1)

Выход:

   A_1  A_2  A_3  A_10  B_1  B_2  B_3  B_10
0   68   59   37    76   11   69   68    17
1   19   52   23    85   37   54   93     3
1
Scott Boston 2 Май 2019 в 18:22

Попробуй это.

Чтобы изменить порядок столбцов на основе номера после имени столбца

cols_fixed = df.columns[:3]  # change index no based on your df
cols_variable = df.columns[3:]  # change index no based on your df
cols_variable = sorted(cols_variable, key=lambda x : int(x.split('_')[1]))  # split based on the number after '_'
cols_new = cols_fixed + cols_variable 
new_df = pd.DataFrame(df[cols_new])

Переупорядочить имена столбцов на основе строковой части И числовой части имен столбцов

cols_fixed = df.columns[:3]  # change index no based on your df
cols_variable = df.columns[3:]  # change index no based on your df
cols_variable = sorted(cols_variable)
cols_new = cols_fixed + cols_variable 
new_df = pd.DataFrame(df[cols_new])
0
Supratim Haldar 2 Май 2019 в 18:47