将整数(正数或负数)拆分为Pandas DataFrame中的多行?
如果我们有以下的数据表:
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
你可以使用 repeat
和 abs
来复制行,并用 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