Как добавить столбец увеличения, который добавляет 1 для каждого нового объекта в csv для определенного идентификатора

#python #pandas #csv

#python #pandas #csv

Вопрос:

У меня есть файл CSV, содержащий информацию о лекарстве (название) и дозе для некоторых пациентов (id), которые принимают.

Файл CSV структурирован следующим образом:

 name, id, dose
ator, 034, 20
ator, 034, 30
para, 034, 30
mar, 035, 20
mar, 034, 10
  

Цель состоит в том, чтобы разобрать его в «длинный» формат со следующими столбцами: «идентификатор», «таблица» (имя таблицы, указанное в коде), поле (т. Е. имя, доза), значение (т. Е. значение, например, name или dose). До сих пор мне удавалось форматировать исходную структуру CSV в это.

Но я также хочу столбец «count», который содержит приращение лекарств, принимаемых каждым пациентом. Например, пациент с идентификатором 034 принимает три лекарства (ator, para и mar), что соответствует количеству 1, 2 и 3. Таким образом, желаемый результат следующий:

 id,table,field,count,value
034, meds, name, 1, ator
034, meds, name, 1, ator
034, meds, name, 2, para
035, meds, name, 1, mar
034, meds, name, 3, mar
034, meds, dose, 1, 20
034, meds, dose, 1, 30
034, meds, dose, 2, 30
035, meds, dose, 1, 20
034, meds, dose, 3, 10
  

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

Но я борюсь с получением такого столбца count.

Я пытался добавить столбец count во фрейм данных с помощью моего кода (пожалуйста, смотрите ниже), но безуспешно.

Любая помощь по созданию этого столбца была бы отличной!

 import pandas as pd

# load the data into a pandas table:
file = '~/data/meds.csv'                   
df = pd.read_table(file, delimiter=',')

#### CANNOT GET THIS PART TO WORK: #####

count = []

for index, row in df.iterrows():
    count.append(df[(df['id'] == row['id']) amp; (df['name'] < row['name'])].shape[0])

df['count'] = count

########################################

# convert data frame into the long format
df = pd.melt(df, id_vars=['id', 'count'], var_name='field', value_name='value')

# Change all NaNs to None 
df = df.where((pd.notnull(df)), None)

# creating new column with table name
table = []
df['table'] = 'meds'

# save to file:
df.to_csv('~/data/meds_out.csv', encoding='utf-8')
  

Комментарии:

1. Кажется, ['study_id', 'recid'] столбцов нет во входных данных, вы можете добавить это?

2. Ах, извините, я изменил study_id на id, чтобы упростить код для этой цели. Я исправлю это во фрагменте кода.

3. Да, значит, решение работает?

4. Вроде того, я бы хотел, чтобы он учитывал лекарства как количество, а не идентификаторы (т. Е. пациент может принимать одно и то же лекарство несколько раз). Но я думаю, это тоже сработает, просто не так, как я себе представлял 🙂 Спасибо.

5. хммм, работаю над этим, дай мне немного времени

Ответ №1:

Используйте melt with GroupBy.cumcount для столбца счетчика:

 df = pd.melt(df, id_vars='id', var_name='field', value_name='value')
#if constant value set this way
df['table'] = 'meds'

df['count'] = df.groupby(['id','field']).cumcount()   1


#change order of columns if necessary
df = df[['id','table','field','count','value']]
print (df)
   id table field  count value
0  34  meds  name      1  ator
1  34  meds  name      2  para
2  35  meds  name      1   mar
3  34  meds  name      3   mar
4  34  meds  dose      1    20
5  34  meds  dose      2    30
6  35  meds  dose      1    20
7  34  meds  dose      3    10
  

Редактировать:

 df['count'] = df.groupby('id')['name'].cumcount()   1
df['count'] = df.groupby('id')['count'].ffill().astype(int)
df = pd.melt(df, id_vars=['id','count'], var_name='field', value_name='value')
print (df)
   id  count field value
0  34      1  name  ator
1  34      2  name  ator
2  34      3  name  para
3  35      1  name   mar
4  34      4  name   mar
5  34      1  dose    20
6  34      2  dose    30
7  34      3  dose    30
8  35      1  dose    20
9  34      4  dose    10
  

Комментарии:

1. Спасибо. Это очень близко, но, к сожалению, один пациент (id) может принимать одно и то же лекарство (название) несколько раз. Ему нужно подсчитывать количество разных лекарств, а не подсчитывать идентификатор. Например, значение ator считается равным 1 для идентификатора 034, во второй раз, когда 034 принимает значение ator, оно снова должно считаться равным 1. Затем 034 принимает значение para, и оно считается как 2. Я надеюсь, что это имеет смысл 🙂