如何在特定数据框中采取差异

时间:2018-01-25 06:14:59

标签: python pandas sorting dataframe diff

我尝试在其中一个数据框列中对连续数字进行区分,同时保留其他列中的顺序,例如:

http://www.example.com/something

我想: - 对于A列(1,2,3和4)的每个独特元素 - 对列B进行排序并获取C列的连续差异

没有循环,得到类似的东西

import pandas as pd

df = pd.DataFrame({"A": [1,1,1,2,2,2,3,3,3,4], 
           "B": [2,1,3,3,2,1,1,2,3,4],
           "C": [2.1,2.0,2.2,1.2,1.1,1.0,3.0,3.1,3.2,3.3]})

In [1]: df
Out[1]: 
   A  B    C
0  1  2  2.1
1  1  1  2.0
2  1  3  2.2
3  2  3  1.4
4  2  2  1.2
5  2  1  1.0
6  3  1  3.0
7  3  2  3.3
8  3  3  3.6
9  4  4  4.0

我已经开展了多项行动:

In [2]: df2
Out[2]: 
    A   B     C    Diff
0   1   2    2.1   0.1
2   1   3    2.2   0.1
3   2   3    1.2   0.2
4   2   2    1.1   0.2
7   3   2    3.1   0.3
8   3   3    3.2   0.3

得到我想要的东西:

df2 = df.groupby(by='A').apply(lambda x: x.sort_values(by = ['B'])['C'].diff())
df3 = pd.DataFrame(df2)
df3.reset_index(inplace=True)
df4 = df3.set_index('level_1')
df5 = df.copy()
df5['diff'] = df4['C']

但是有更有效的方法吗? (可以很容易地删除NaN值,因此我不会对该部分挑剔)

1 个答案:

答案 0 :(得分:0)

有点不清楚预期的结果是什么(为什么行数较少?)。

对于采取连续差异,您可能希望使用Series.diff()see docs here

df['Diff'] = df.C.diff()

如果您想要一些(正面或负面)滞后来取得差异,可以使用period关键字。

不要看排序部分生效的位置,但为此您可能想要使用Series.sort_values()see docs here

修改 根据您的最新信息,我相信这可能是您正在寻找的:

df.sort_values(by=['B', 'C'], inplace=True)
df['diff'] = df.C.diff()

编辑2 根据有关计算的更新信息,您需要:
- 由A组成的组(参见DataFrame.groupby() here上的文档)
- 按B 排序(每组)(或按A然后按B预先分组)
- 计算C的差异(并忽略第一条记录,因为它将丢失)。

以下代码实现了:

df.sort_values(by=['A','B'], inplace=True)
df['Diff'] = df.groupby('A').apply(lambda x: x['C'].diff()).values
df2 = df.dropna()

代码说明: 第一行首先对数据帧进行排序。

第二行有很多事情要发生......:

  • 首先groupby(现在会生成分组的DataFrame ,如果您是该群组的新用户,请参阅有帮助的pandas page on split-apply-combine
  • 然后获得每组的C差异
  • 和" flatten"通过获取具有.values
  • 的系列来分组数据框 我们分配给df['Diff']
  • (这就是为什么我们需要预先分配数据帧,所以这个赋值会正确...如果不是我们必须合并A和B上的系列)。

第三行只删除了NA并将其分配给df2

<强> EDIT3 我认为我的EDIT2版本可能就是您正在寻找的,更简洁,更少的辅助数据生成。但是,您也可以通过以下方式改进您的解决方案版本:

df3.reset_index(level=0, inplace=True)  # no need to reset and then set again
df5 = df.copy()      # only if you don't want to change df
df5['diff'] = df3.C  #  else, just do df.insert(2, 'diff', df3.C)