如何在特定的数据框架中获取差异

2022-09-28 21:20:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我尝试在一个dataframe列中取连续数字的差,同时在另一列中保留顺序,例如:

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

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

没有循环,得到这样的东西

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']

得到了我想要的:

df5
Out[1]: 
   A  B  C     diff
0  1  2  2.1   0.1
1  1  1  2.0   NaN
2  1  3  2.2   0.1
3  2  3  1.2   0.1
4  2  2  1.1   0.1
5  2  1  1.0   NaN
6  3  1  3.0   NaN
7  3  2  3.1   0.1
8  3  3  3.2   0.1
9  4  4  3.3   NaN

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


Tags: indataframedfindexbydiff数字nanoutpddf2df3df4df5
1条回答
网友
1楼 ·

对预期结果有点不清楚(为什么行数较少?)。你知道吗

对于获取连续差异您可能需要使用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排序,再按groupby排序)
-计算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(现在生成一个分组数据帧,如果您是groupby新手,请参阅有用的pandas page on split-apply-combine
  • 然后得出各组C的差异
  • 以及通过获得具有.values的序列来“展平”分组的数据帧
  • 我们将其分配给df['Diff'](这就是为什么我们需要对数据帧进行预排序,这样这个分配就可以得到正确的结果。。。如果不是,我们将不得不合并A和B)上的序列。你知道吗

第三行只是删除NAs并将其分配给df2。你知道吗


编辑3 我想我的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)

热门问题