Pandas数据框中一列值数量不固定

-1 投票
3 回答
104 浏览
提问于 2025-04-14 18:13

假设我有一个这样的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 把每个年龄拆分成一行。这样做会让 idchildren_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

如果你想要一个整齐的格式(也就是长格式),可以使用extractalljoin

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

撰写回答