样本数据:
sample = pd.DataFrame({'split_me': [1.5, 2, 4, 3.2], 'copy_me': ['A', 'B', 'C', 'D']})
out = pd.DataFrame({'split_me': [1, 0.5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.2], 'copy_me': ['A', 'A', 'B', 'B', 'C', 'C', 'C', 'C', 'D', 'D', 'D', 'D']})
sample: # input
split_me copy_me
0 1.5 A
1 2.0 B
2 4.0 C
3 3.2 D
out: # desired output
split_me copy_me
0 1.0 A
1 0.5 A
2 1.0 B
3 1.0 B
4 1.0 C
5 1.0 C
6 1.0 C
7 1.0 C
8 1.0 D
9 1.0 D
10 1.0 D
11 0.2 D
我试过使用sample.loc[sample.index.repeat(sample['split_me'])]
之类的东西。然而,这只对整数重复,当我需要它返回2时,像1.9这样的值返回1行,并且它使split_me
中的值保持不变,而我需要复制行,如果大于1,则将1分配给split_me
,否则分配值。
我想不出一种方法来做到这一点,而不会变得循环和复杂,我最好的方法是ceil(split_me)
,然后运行repeat
,但我仍然需要一种方法来分配值到重复的行。寻找一个更简单的解决方案,如果有人有的话。
是的,我们可以这样做
out = sample.reindex(sample.index.repeat(np.ceil(sample['split_me'])))
out['new'] = 1
con = ~out['copy_me'].duplicated(keep='last') & (out['split_me']%1!=0)
out['new'] = out['new'].mask(con, out['split_me']%1)
out
Out[195]:
split_me copy_me new
0 1.5 A 1.0
0 1.5 A 0.5
1 2.0 B 1.0
1 2.0 B 1.0
2 4.0 C 1.0
2 4.0 C 1.0
2 4.0 C 1.0
2 4.0 C 1.0
3 3.2 D 1.0
3 3.2 D 1.0
3 3.2 D 1.0
3 3.2 D 0.2
使用自定义重复函数
repeat_float = lambda x: ([1.] * int(x // 1)) + ([x % 1] if x % 1 != 0 else [])
out = df['split_me'].apply(repeat_float).explode().astype(float)
.to_frame().join(df['copy_me']).reset_index(drop=True)
输出:
>>> out
split_me copy_me
0 1.0 A
1 0.5 A
2 1.0 B
3 1.0 B
4 1.0 C
5 1.0 C
6 1.0 C
7 1.0 C
8 1.0 D
9 1.0 D
10 1.0 D
11 0.2 D
我们可以使用np.modf
将split_me
的小数部分和整数部分分开,然后基于唯一的整数部分的repeat
创建一个新的1系列。append
非零小数部分,sort_index
进入预期的顺序,最后join
返回列,reset_index
恢复范围索引:
fractional, integral = np.modf(sample['split_me'])
df = (
pd.Series(1, index=integral.index.repeat(integral), name=integral.name)
.append(fractional[fractional.ne(0)]).sort_index(kind='stable')
.to_frame().join(sample[['copy_me']]).reset_index(drop=True)
)
df
:
split_me copy_me
0 1.0 A
1 0.5 A
2 1.0 B
3 1.0 B
4 1.0 C
5 1.0 C
6 1.0 C
7 1.0 C
8 1.0 D
9 1.0 D
10 1.0 D
11 0.2 D
Setup and imports:
import numpy as np
import pandas as pd
sample = pd.DataFrame({
'split_me': [1.5, 2, 4, 3.2],
'copy_me': ['A', 'B', 'C', 'D']
})
尝试:
import pandas as pd
import numpy as np
sample = pd.DataFrame({'split_me': [1.5, 2, 4, 3.2], 'copy_me': ['A', 'B', 'C', 'D']})
def expanded_index(s, c):
index = np.repeat(1.0, s // 1)
if (s % 1) > 0:
index = np.append(index, [s % 1])
return pd.Series(c, index)
res = pd.concat([expanded_index(s, c) for s, c in zip(sample["split_me"], sample["copy_me"])])
print(res)
1.0 A
0.5 A
1.0 B
1.0 B
1.0 C
1.0 C
1.0 C
1.0 C
1.0 D
1.0 D
1.0 D
0.2 D
dtype: object