#python #pandas #database #dataframe #data-analysis
Вопрос:
У меня есть беспорядочный большой CSV-файл с большим количеством значений Nan, и я читаю фрейм данных с помощью pd.read_csv(file, names = range(int))
. Я хотел разделить эти данные на несколько фреймов данных и сохранить в словаре, используя заданный ключ в данных. Я подготовил простой пример, чтобы объяснить свою проблему.
Пример rawdata: Мои данные выглядят аналогично приведенным, но с большим количеством столбцов и строк.
import pandas as pd
import numpy as np
df = pd.DataFrame(columns=([1,2,3,4]))
df.loc[0,:] = ['Home -AA',np.nan,np.nan,np.nan]
df.loc[1,:] = ['place/time','value1','value2','value3']
df.loc[2,:] = ['Home time1',1, 2, 3]
df.loc[3,:] = ['Home time2',4, 5, 6]
df.loc[4,:] = ['Home time3',7, 8, 9]
df.loc[5,:] = ['sum',11,np.nan , np.nan]
df.loc[6,:] = ['agg',12,np.nan , np.nan]
df.loc[7,:] = ['max',6,np.nan , np.nan]
df.loc[8,:] = ['min',8,np.nan , np.nan]
df.loc[9,:] = ['med',1,np.nan , np.nan]
df.loc[10,:] = ['Home -BB',np.nan,np.nan,np.nan]
df.loc[11,:] = ['place/time','value1','value2','value3']
df.loc[12,:] = ['Home time1',11, 12, 13]
df.loc[13,:] = ['Home time2',14, 15, 16]
df.loc[14,:] = ['Home time3',17, 18, 19]
df.loc[15,:] = ['sum',101,np.nan , np.nan]
df.loc[16,:] = ['agg',122,np.nan , np.nan]
df.loc[17,:] = ['max',62,np.nan , np.nan]
df.loc[18,:] = ['min',83,np.nan , np.nan]
df.loc[19,:] = ['med',12,np.nan , np.nan]
df.loc[20,:] = ['Home -CC',np.nan,np.nan,np.nan]
df.loc[21,:] = ['place/time','value1','value2','value3']
df.loc[22,:] = ['Home -DD',np.nan,np.nan,np.nan]
df.loc[23,:] = ['place/time','value1','value2','value3']
df.loc[24,:] = ['Home -EE',np.nan,np.nan,np.nan]
df.loc[25,:] = ['place/time','value1','value2','value3']
df.loc[26,:] = ['Home -FF',np.nan,np.nan,np.nan]
df.loc[27,:] = ['place/time','value1','value2','value3']
df.loc[28,:] = ['Home time1',211, 212, 213]
df.loc[29,:] = ['Home time1',212, 213, 214]
df.loc[30,:] = ['sum',115,np.nan , np.nan]
df.loc[31,:] = ['agg',124,np.nan , np.nan]
df.loc[32,:] = ['max',65,np.nan , np.nan]
df.loc[33,:] = ['min',85,np.nan , np.nan]
df.loc[34,:] = ['med',16,np.nan , np.nan]
Желаемые результаты: Я хочу преобразовать этот фрейм данных в несколько фреймов данных с определением ключей дома и сохранением, как в словаре dict1. (Пример результата)
df1 = pd.DataFrame(columns=([1,2,3,4]))
df1.loc[1,:] = ['place/time','value1','value2','value3']
df1.loc[2,:] = ['Home time1',1, 2, 3]
df1.loc[3,:] = ['Home time2',4, 5, 6]
df1.loc[4,:] = ['Home time3',7, 8, 9]
df2 = pd.DataFrame(columns=([1,2,3,4]))
df2.loc[11,:] = ['place/time','value1','value2','value3']
df2.loc[12,:] = ['Home time1',11, 12, 13]
df2.loc[13,:] = ['Home time2',14, 15, 16]
df2.loc[14,:] = ['Home time3',17, 18, 19]
df3 = pd.DataFrame(columns=([1,2,3,4]))
df3.loc[21,:] = ['place/time','value1','value2','value3']
df4 = pd.DataFrame(columns=([1,2,3,4]))
df4.loc[23,:] = ['place/time','value1','value2','value3']
df5 = pd.DataFrame(columns=([1,2,3,4]))
df5.loc[25,:] = ['place/time','value1','value2','value3']
df6 = pd.DataFrame(columns=([1,2,3,4]))
df6.loc[27,:] = ['place/time','value1','value2','value3']
df6.loc[28,:] = ['Home time1',211, 212, 213]
df6.loc[29,:] = ['Home time1',212, 213, 214]
dict1 = {'House -AA':df1, 'House -BB': df2,'House -CC': df3 , 'House -DD':df4, 'House -EE':df5, 'House -FF':df6}
Подготовил код, используя цикл for, но я не могу правильно разделить весь фрейм данных. Если я не разорву цикл, то получу ошибку (индекс списка вне диапазона). Не могли бы вы, пожалуйста, помочь мне получить аналогичные результаты, как я объяснил выше?
Подготовленная идея кода:
namesplit = lambda x: x.split('-')[0]
postion = 'Home '
rawname = []
for i in df[1]:
x = namesplit(i)
if postion == x:
rawname.append(i)
test = {}
for i in range(len(rawname)):
x = df[df[1]==rawname[i]].index.values
y = df[df[1]==rawname[i 1]].index.values
if y == len(df) -9:
break
df_1 = df.iloc[x[0]:y[0], :]
test[rawname[i]] = df_1
Ответ №1:
Вы можете просто использовать groupby
и cumsum
:
result = {}
for _, i in df.groupby(df[1].str.startswith("Home -").cumsum()):
name, d = i[1].iat[0], i.iloc[1:]
result[name] = d[~d[1].isin(["sum","agg","max","min","med"])]
print (result)
{'Home -AA': 1 2 3 4
1 place/time value1 value2 value3
2 Home time1 1 2 3
3 Home time2 4 5 6
4 Home time3 7 8 9,
'Home -BB': 1 2 3 4
11 place/time value1 value2 value3
12 Home time1 11 12 13
13 Home time2 14 15 16
14 Home time3 17 18 19,
'Home -CC': 1 2 3 4
21 place/time value1 value2 value3,
'Home -DD': 1 2 3 4
23 place/time value1 value2 value3,
'Home -EE': 1 2 3 4
25 place/time value1 value2 value3,
'Home -FF': 1 2 3 4
27 place/time value1 value2 value3
28 Home time1 211 212 213
29 Home time1 212 213 214}
Ответ №2:
Вы можете сделать это, выполнив цикл по полному кадру данных и выделив меньшие кадры данных в строках-разделителях. Это грубая сила, но она работает.
results = {}
for i, row in df.iterrows():
if "Home -" in row[1]:
accumulator = pd.DataFrame(columns=[1, 2, 3, 4])
key = row[1]
results[key] = accumulator
else:
results[key] = results[key].append(row)
Выход:
In [9]: results
Out[9]:
{'Home -AA': 1 2 3 4
1 place/time value1 value2 value3
2 Home time1 1 2 3
3 Home time2 4 5 6
4 Home time3 7 8 9
5 sum 11 NaN NaN
6 agg 12 NaN NaN
7 max 6 NaN NaN
8 min 8 NaN NaN
9 med 1 NaN NaN,
'Home -BB': 1 2 3 4
11 place/time value1 value2 value3
12 Home time1 11 12 13
13 Home time2 14 15 16
14 Home time3 17 18 19
15 sum 101 NaN NaN
16 agg 122 NaN NaN
17 max 62 NaN NaN
18 min 83 NaN NaN
19 med 12 NaN NaN,
'Home -CC': 1 2 3 4
21 place/time value1 value2 value3,
'Home -DD': 1 2 3 4
23 place/time value1 value2 value3,
'Home -EE': 1 2 3 4
25 place/time value1 value2 value3,
'Home -FF': 1 2 3 4
27 place/time value1 value2 value3
28 Home time1 211 212 213
29 Home time1 212 213 214
30 sum 115 NaN NaN
31 agg 124 NaN NaN
32 max 65 NaN NaN
33 min 85 NaN NaN
34 med 16 NaN NaN}
Ответ №3:
Причина, по которой вы получаете ошибку индекса списка вне диапазона, заключается в том, что y
в вашем цикле используется i 1
значение вашего списка rawname
. Таким образом, вы хотите выполнить цикл только до len(rawname)-1
следующего:
test = {}
for i in range(len(rawname)-1):
x = df[df[1]==rawname[i]].index.values
y = df[df[1]==rawname[i 1]].index.values
df_1 = df.iloc[x[0]:y[0], :]
test[rawname[i]] = df_1