Pandas数据框中一列值数量不固定
假设我有一个这样的Pandas数据框:
import pandas as pd
import numpy as np
ids = np.arange(1, 21)
children_count = np.random.randint(1, 16, size=len(ids)).astype(float)
children_count[np.random.choice(len(ids), size=10, replace=False)] = np.nan # Adding some NaN values
def generate_age_string(count):
if np.isnan(count):
return np.nan
else:
ages = [str(np.random.randint(0, 19)) + " years" for _ in range(int(count))]
return " and ".join(ages)
age = [generate_age_string(count) for count in children_count]
df = pd.DataFrame({
'id': ids,
'children_count': children_count,
'age': age
})
print(df)
我应该采取什么方法来整理age
这一列的数据呢?我并没有特别想要的输出结果。唯一想到的就是为每个年龄创建一个额外的列,但这样可能会增加太多列。有没有其他可行的选择呢?
3 个回答
1
你可以通过使用Pandas的explode函数,为列表中的每个项目创建单独的行。
1
这要看你打算怎么使用这些数据。
你可以提取出年龄,然后用 Series.str.findall
把它们放进列表里:
df["age"] = df["age"].dropna().str.findall(r"\b\d+\b")
id children_count age
0 1 NaN NaN
1 2 NaN NaN
2 3 14.0 [0, 5, 5, 4, 11, 14, 3, 4, 8, 14, 3, 9, 0, 0]
3 4 9.0 [12, 1, 14, 14, 12, 8, 1, 7, 5]
...
之后,你还可以用 df.explode
把每个年龄拆分成一行。这样做会让 id
和 children_count
这两列的数据重复,但这是否合适,还是要看你打算怎么使用这些数据。
df = df.explode(column="age")
id children_count age
0 1 1.0 0
1 2 NaN NaN
2 3 11.0 9
2 3 11.0 12
2 3 11.0 18
.. .. ... ...
18 19 11.0 12
18 19 11.0 16
18 19 11.0 9
18 19 11.0 4
19 20 NaN NaN
最后,除非你有特别的需求,否则我觉得为每个年龄创建新的列并没有太大意义。
2
如果你想要一个整齐的格式(也就是长格式),可以使用extractall
和join
:
out = (df.drop(columns='age')
.join(df['age'].str.extractall(r'(?P<age>\d+)\syears')
.droplevel('match'))
)
输出结果:
id children_count age
0 1 NaN NaN
1 2 NaN NaN
2 3 NaN NaN
3 4 7.0 6
3 4 7.0 4
.. .. ... ...
19 20 13.0 9
19 20 13.0 14
19 20 13.0 5
19 20 13.0 9
19 20 13.0 3
[79 rows x 3 columns]
另外,如果你想要一个宽格式(这样会浪费更多空间,特别是当孩子的数量不同时),可以在连接之前使用unstack
:
out = (df.drop(columns='age')
.join(df['age'].str.extractall(r'(\d+)\syears')[0]
.unstack('match').add_prefix('Child'))
)
输出结果:
id children_count Child0 Child1 Child2 Child3 Child4 Child5 Child6 Child7 Child8 Child9 Child10 Child11 Child12
0 1 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1 2 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2 3 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3 4 7.0 6 4 10 16 6 13 14 NaN NaN NaN NaN NaN NaN
4 5 11.0 7 9 12 16 16 4 6 12 16 7 1 NaN NaN
5 6 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
6 7 13.0 17 17 18 11 1 17 1 3 16 9 7 11 0
7 8 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
8 9 9.0 12 7 8 17 9 1 13 13 11 NaN NaN NaN NaN
9 10 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
10 11 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
11 12 2.0 12 14 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
12 13 6.0 11 12 4 6 8 3 NaN NaN NaN NaN NaN NaN NaN
13 14 3.0 18 12 12 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
14 15 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
15 16 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
16 17 1.0 11 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
17 18 4.0 13 13 8 0 NaN NaN NaN NaN NaN NaN NaN NaN NaN
18 19 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
19 20 13.0 18 18 4 1 13 14 7 7 9 14 5 9 3