#python #python-3.x #pandas #string #csv
#python #python-3.x #pandas #строка #csv
Вопрос:
У меня есть файл csv следующим образом:
name,row,column,length_of_field
AB000M,8,12,1
AB000M,9,12,1
AB000M,10,0,80
AB000M,10,12,1
AB000M,11,1,1
AB000M,21,0,80
AB000M,22,0,80
Что я пытаюсь сделать, так это всякий раз, когда поле столбца равно 0, добавьте длину поля в столбец, и строка должна быть уменьшена на 1. Также, если есть последующая строка, где столбец снова равен 0, затем добавьте в столбец первую длину поля, уменьшите строку на 1 для первого вхождения и добавьте длины полей вместе. А затем удалите старые строки.
Таким образом, в приведенном выше csv-файле «AB000M, 10,0,80» станет «AB000M, 9,80,80» и «AB000M, 21,0,80 AB000M,22,0,80
» — эти две строки следует заменить на «AB000M,20,80,160».
Я пытаюсь добиться этого с помощью этого фрагмента, но он не работает:
df = pd.read_csv("file.csv")
for ind in df.index:
if ind >= len(df)-1:
break
if df['column'][ind] == 0 and df['column'][ind 1] != 0:
df['row'][ind] -= 1
df['column'][ind] = 80
elif df['column'][ind] == 0 and df['column'][ind 1] == 0:
df['row'][ind] -= 1
df['column'][ind] = 80
df['length_of_field'][ind] = df['length_of_field'][ind 1]
df.drop([df.index[ind 1]], axis=0)
Ответ №1:
Это пример того, что может сработать для вас.
import pandas as pd
df = pd.read_csv('test.csv')
newRows = []
last_val_is_zero = False
tempRow = None
for row in df.iterrows():
vals = row[1]
if vals['column'] == 0:
if not last_val_is_zero:
vals['row'] = vals['row'] - 1
vals['column'] = vals['length_of_field']
tempRow = vals
last_val_is_zero = True
else:
tempRow['length_of_field'] = tempRow['length_of_field'] vals['length_of_field']
else:
if tempRow is not None:
newRows.append(tempRow)
newRows.append(vals)
tempRow = None
last_val_is_zero = False
if tempRow is not None:
newRows.append(tempRow)
newData = [[val for val in row] for row in newRows]
newDf = pd.DataFrame(newData, columns=[x for x in newRows[0].keys()])
Ответ №2:
пример данных:
df_str = '''
name,row,column,length_of_field
AB000M,8,12,1
AB000M,9,12,1
AB000M,10,0,80
AB000M,10,12,1
AB000M,11,1,1
AB000M,21,0,80
AB000M,22,0,80
AB000M,23,11,1
AB000M,24,11,1
AB000M,25,0,80
AB000M,26,0,80
AB000M,27,0,80
AB000M,28,11,1
AB000M,29,0,80
'''
df = pd.read_csv(io.StringIO(df_str.strip()), sep=',', index_col=False)
решение:
# split the row which to update or left
cond = df['column'] == 0
df_to_update = df[cond].copy()
df_left = df[~cond].copy()
# modify the update rows
df_to_update['column'] = df_to_update['length_of_field']
df_to_update['row'] -= 1
# create tag for which is diff 1 with the previous row
cond = df_to_update['row'].diff() != 1
df_to_update['tag'] = np.where(cond, 1, 0)
# cumsum tag to creat group
df_to_update['label'] = df_to_update['tag'].cumsum()
print(df_to_update)
# name row column length_of_field tag label
# 2 AB000M 9 80 80 1 1
# 5 AB000M 20 80 80 1 2
# 6 AB000M 21 80 80 0 2
# 9 AB000M 24 80 80 1 3
# 10 AB000M 25 80 80 0 3
# 11 AB000M 26 80 80 0 3
# 13 AB000M 28 80 80 1 4
# agg groupy left first row, and sum(length_of_field)
obj_list = []
for tag, group in df_to_update.groupby('label'):
obj = group.iloc[0].copy()
obj['length_of_field'] = group['length_of_field'].sum()
obj_list.append(obj)
dfn_to_update = pd.concat(obj_list,axis=1).T[df.columns]
# merge final result
dfn = df_left.append(dfn_to_update).sort_index()
Результат:
print(dfn)
name row column length_of_field
0 AB000M 8 12 1
1 AB000M 9 12 1
2 AB000M 9 80 80
3 AB000M 10 12 1
4 AB000M 11 1 1
5 AB000M 20 80 160
7 AB000M 23 11 1
8 AB000M 24 11 1
9 AB000M 24 80 240
12 AB000M 28 11 1
13 AB000M 28 80 80
print(df)
name row column length_of_field
0 AB000M 8 12 1
1 AB000M 9 12 1
2 AB000M 10 0 80
3 AB000M 10 12 1
4 AB000M 11 1 1
5 AB000M 21 0 80
6 AB000M 22 0 80
7 AB000M 23 11 1
8 AB000M 24 11 1
9 AB000M 25 0 80
10 AB000M 26 0 80
11 AB000M 27 0 80
12 AB000M 28 11 1
13 AB000M 29 0 80