将整数(正数或负数)拆分为Pandas DataFrame中的多行?

0 投票
3 回答
38 浏览
提问于 2025-04-12 17:55

如果我们有以下的数据表:

df = pd.DataFrame({'String_Column': ['A', 'B', 'C'],
                   'String_Column_2': ['X', 'Y', 'Z'],
                   'Integer_Column': [1, -2, 3]})

我想把这个表格从这样的样子:

字符串列 字符串列2 整数列
A X 1
B Y -2
C Z 3

变成这样的样子:

字符串列 字符串列2 整数列
A X 1
B Y -1
B Y -1
C Z 1
C Z 1
C Z 1

我刚开始学习Python……

3 个回答

0

你可以使用 repeatabs 来复制行,并用 numpy.sign 来转换整数列:

out = (df.loc[df.index.repeat(df['Integer_Column'].abs())]
         .assign(Integer_Column=lambda d: np.sign(d['Integer_Column']))
      )

# or reversing the operations, which might be a bit more efficient
# out = (df.assign(Integer_Column=lambda d: np.sign(d['Integer_Column']))
#          .loc[df.index.repeat(df['Integer_Column'].abs())]
#       )

另外一个选择是使用 groupby.transform 来生成 1-1

out = df.loc[df.index.repeat(df['Integer_Column'].abs())]

out['Integer_Column'] /= out.groupby(level=0).transform('size')

输出结果:

  String_Column String_Column_2  Integer_Column
0             A               X               1
1             B               Y              -1
1             B               Y              -1
2             C               Z               1
2             C               Z               1
2             C               Z               1
1

另一种可能的解决方案是,首先从每个 Integer_Column 列的值创建一个包含 1-1 的列表,然后使用 explode 方法。

(df.assign(Integer_Column = df['Integer_Column']
           .map(lambda x: [np.sign(x)]*abs(x)))
 .explode('Integer_Column'))

下面的解决方案似乎效率稍微高一点,但也没高多少,因为使用了 explode,正如 @mozway 在下面的评论中恰当地指出的那样。

signs = np.sign(df['Integer_Column'])
lengths = abs(df['Integer_Column'])

(df.assign(Integer_Column = [np.full(abs_len, sign) 
                             for sign, abs_len in zip(signs, lengths)])
 .explode('Integer_Column'))

输出结果:

  String_Column String_Column_2 Integer_Column
0             A               X              1
1             B               Y             -1
1             B               Y             -1
2             C               Z              1
2             C               Z              1
2             C               Z              1
1

请将行重复指定的次数,然后根据这个整数值是否小于0来更新它。

代码:

import pandas as pd

df = pd.DataFrame({'String_Column': ['A', 'B', 'C'],
                   'String_Column_2': ['X', 'Y', 'Z'],
                   'Integer_Column': [1, -2, 3]})

df_repeated = df.loc[df.index.repeat(df['Integer_Column'].apply(lambda x: abs(x)))].copy() # repeat rows absolute of integer
df_repeated['Integer_Column'] = df_repeated['Integer_Column'].apply(lambda x: -1 if x < 0 else 1) # if x <0: -1, else 1
df_repeated.reset_index(drop=True, inplace=True)

print(df_repeated)

输出:

  String_Column String_Column_2  Integer_Column
0             A               X               1
1             B               Y              -1
2             B               Y              -1
3             C               Z               1
4             C               Z               1
5             C               Z               1

撰写回答