我如何获取 Pandas DataFrame,根据条件拆分它,并将生成的 DataFrame 作为值保存在具有预先指定键的 dict 对象中?
我有一个 Pandas 数据框(来自 R's networkDynamicData 包的 hospital.dat_ 数据)。我读入它并将其作为 Pandas DataFrame 处理,如下所示:
with open('hospital.dat_', 'r') as f:
data = f.readlines()
#Convert to a pandas dataframe for easier manipulation
split_data = []
for line in data:
split_line = line.split('\t')
split_data.append(split_line)
df = pd.DataFrame(split_data)
df.columns=['Time', 'ID1', 'ID2', 'Att1', 'Att2'] #assign column names
DataFrame df
看起来像这样:
print df.head()
Time ID1 ID2 Att1 Att2
0 140 1157 1232 MED ADM\n
1 160 1157 1191 MED MED\n
2 500 1157 1159 MED MED\n
3 520 1157 1159 MED MED\n
4 560 1159 1191 MED MED\n
我想根据Time
将DataFrame
分成多个部分。作为 MWE,假设我想要一个具有三个 DataFrame
值的 dict
对象:
- 包含
Time
小于 200 的条目的所有行;
- 包含
Time
大于 200 但小于 550 的条目的所有行;
- 包含
Time
条目的所有行大于 550 但小于 600(剩下的所有)
- 开始的时间索引是关键。
也就是说,我想要:
0:
Time ID1 ID2 Att1 Att2
0 140 1157 1232 MED ADM\n
1 160 1157 1191 MED MED\n
200:
Time ID1 ID2 Att1 Att2
0 500 1157 1159 MED MED\n
1 520 1157 1159 MED MED\n
550:
Time ID1 ID2 Att1 Att2
0 560 1159 1191 MED MED\n
我有一个列表,其中包含拆分值,末尾为 0 和最大值:
my_list = [0, 200, 550, 600]
作为开始,我试过:
sorted_df = {i : [df.loc[(df['Time'] > i) & (df['Time'] <= j)] for i, j in enumerate(my_list)]}
但这只给了我一个键,因为我一直在覆盖,而值是空列表。
问题:我如何获取 Pandas DataFrame,根据条件拆分它,并将生成的 DataFrame 作为值保存在具有预先指定键的 dict 对象中?
您可以使用 cut
用于垃圾箱,然后转换 groupby
反对 dict
:
df = pd.read_table('hospital.dat_')
cat= pd.cut(df['Time'], bins=my_list, labels = my_list[:-1], include_lowest=True)
print (cat)
0 0
1 0
2 200
3 200
4 550
Name: Time, dtype: category
Categories (3, int64): [0 < 200 < 550]
dfs = dict(tuple(df.groupby(cat)))
print (dfs)
{0: Time ID1 ID2 Att1 Att2
0 140 1157 1232 MED ADM
1 160 1157 1191 MED MED, 200: Time ID1 ID2 Att1 Att2
2 500 1157 1159 MED MED
3 520 1157 1159 MED MED, 550: Time ID1 ID2 Att1 Att2
4 560 1159 1191 MED MED}
print (dfs[0])
Time ID1 ID2 Att1 Att2
0 140 1157 1232 MED ADM
1 160 1157 1191 MED MED
print (dfs[200])
Time ID1 ID2 Att1 Att2
2 500 1157 1159 MED MED
3 520 1157 1159 MED MED
也可以通过字典理解创建默认索引:
dfs = {k:v.reset_index(drop=True) for k, v in df.groupby(cat)}
print (dfs[0])
Time ID1 ID2 Att1 Att2
0 140 1157 1232 MED ADM
1 160 1157 1191 MED MED
print (dfs[200])
Time ID1 ID2 Att1 Att2
0 500 1157 1159 MED MED
1 520 1157 1159 MED MED
如果想要没有 cut/groupby
的解决方案,您可以zip
没有 last 的列表的所有值和没有 first 的所有值,并使用 dict comprehension
:
zipped = zip(my_list[:-1], my_list[1:])
print (list(zipped))
[(0, 200), (200, 550), (550, 600)]
sorted_df = {i : df.loc[(df['Time'] > i) & (df['Time'] <= j)].reset_index(drop=True)
for i, j in zipped}
print (sorted_df)
{0: Time ID1 ID2 Att1 Att2
0 140 1157 1232 MED ADM
1 160 1157 1191 MED MED, 200: Time ID1 ID2 Att1 Att2
0 500 1157 1159 MED MED
1 520 1157 1159 MED MED, 550: Time ID1 ID2 Att1 Att2
0 560 1159 1191 MED MED}
我是一名优秀的程序员,十分优秀!