如何在特定数据框中采取差异
How to take difference in a specific 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 值可以很容易地删除,所以我对那部分不挑剔)
不太清楚预期的结果(为什么行数较少?)。
对于取连续差值你可能想使用Series.diff()
(see docs here)
df['Diff'] = df.C.diff()
如果您想要一些(正或负)滞后来计算差异,您可以使用 period
关键字。
看不到 sort 部分在哪里生效,但为此你可能想使用 Series.sort_values()
(see docs here)
编辑
根据您更新的信息,我相信这可能是您正在寻找的:
df.sort_values(by=['B', 'C'], inplace=True)
df['diff'] = df.C.diff()
编辑 2
根据您的 new 更新的计算信息,您想要:
- 按 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()
代码解释:
第一行首先对数据框进行排序。
第二行有一堆事情要发生...:[=26=]
- 首先
groupby
(现在生成一个 分组数据帧,如果您是 groupby 的新手,请参阅有用的 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)
我试图在其中一个数据框列中取连续数字的差异,同时在另一列中保留顺序,例如:
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 值可以很容易地删除,所以我对那部分不挑剔)
不太清楚预期的结果(为什么行数较少?)。
对于取连续差值你可能想使用Series.diff()
(see docs here)
df['Diff'] = df.C.diff()
如果您想要一些(正或负)滞后来计算差异,您可以使用 period
关键字。
看不到 sort 部分在哪里生效,但为此你可能想使用 Series.sort_values()
(see docs here)
编辑 根据您更新的信息,我相信这可能是您正在寻找的:
df.sort_values(by=['B', 'C'], inplace=True)
df['diff'] = df.C.diff()
编辑 2
根据您的 new 更新的计算信息,您想要:
- 按 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()
代码解释: 第一行首先对数据框进行排序。
第二行有一堆事情要发生...:[=26=]
- 首先
groupby
(现在生成一个 分组数据帧,如果您是 groupby 的新手,请参阅有用的 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)