所以我是Pandas的新手,我试图将旧代码转换为DataFrames和Series。我的数据框看起来像这样:
time data param
t0 -1 x
t1 0 z
t2 -1 y
t3 1 x
t4 -1 y
我需要为每1到-1和-1到1的转换插入中间行。此行应包含回填时间和参数,数据值应为零。
这是在该操作之后的样子:
time data param
t0 -1 x
t1 0 z
t2 -1 y
t3 0 x <-- added row
t3 1 x
t4 0 y <-- added row
t4 -1 y
那我怎么能做到这一点?我想我可以通过逐行扫描原始数据并将最后保存的数据值与当前值进行比较来创建新的DataFrame,在需要时产生额外的零。你能建议更好的解决方案,避免逐行迭代吗?
更新
在阅读了Primer的回答之后,我又找到了另一个解决方案:
阅读数据:
import pandas as pd
df = pd.read_csv(pd.io.common.StringIO("""time data param
t0 -1 x
t1 0 z
t2 -1 y
t3 1 x
t4 -1 y"""), sep='\s+')
df
查找1-&gt; -1和-1-&gt; 1转换,计算它们,更改索引值,重新索引全范围以引入缺失的行
df.index += (df.data * df.data.shift() < 0).astype(int).cumsum()
df = df.reindex(arange(df.index[-1] + 1))
填写缺失值
df[['time','param']] = df[['time','param']].bfill()
df.data.fillna(0, inplace=True)
我还在寻找更好的解决方案。请分享您的想法。
答案 0 :(得分:1)
你可以这样做:
import pandas as pd
df = pd.read_csv(pd.io.common.StringIO("""time data param
t0 -1 x
t1 0 z
t2 -1 y
t3 1 x
t4 -1 y"""), sep='\s+')
df['count'] = arange(df.shape[0])
df
设置过滤器,以便将更改从-1更改为1并返回:
d1to_1 = (df.data == -1) & (df.data.shift() == 1)
d_1to1 = (df.data == 1) & (df.data.shift() == -1)
将数据复制到新数据帧(以避免SettingWithCopyWarning):
df1to_1 = df.loc[d1to_1].copy(deep=True)
df_1to1 = df.loc[d_1to1].copy(deep=True)
根据您的需要修改新数据,更改计数器以确保新行高于旧行:
df_1to1['data'] = 0
df_1to1['count'] = df_1to1['count'] - 1
df1to_1['data'] = 0
df1to_1['count'] = df1to_1['count'] - 1
Concat旧的和新的数据帧,按时间和计数器排序,然后重置索引。
df = pd.concat([df, df1to_1, df_1to1], ignore_index=True).sort(['time','count']).reset_index(drop=True)
del df['count']
df
这应该产生所需的输出:
time data param
0 t0 -1 x
1 t1 0 z
2 t2 -1 y
3 t3 0 x
4 t3 1 x
5 t4 0 y
6 t4 -1 y
如果您可以使用旧行之后的新行,则可以跳过counter
部分。