分组 DataFrame,将函数与输入一起应用,然后将结果添加回原始数据
Group DataFrame, apply function with inputs then add result back to original
在任何地方都找不到这个问题,所以只需在这里试试:
我想做的基本上是使用 groupby 功能和一个自写函数来改变现有的 DataFrame 对象:
benchmark =
x y z field_1
1 1 3 a
1 2 5 b
9 2 4 a
1 2 5 c
4 6 1 c
我想做的是分组 field_1
,应用一个使用特定列作为输入的函数,在本例中是列 x
和 y
,然后加回结果到原始 DataFrame benchmark
作为一个名为 new_field
的新列。函数本身取决于 field_1
中的值,即 field_1=a
与 field_1=b
等相比将产生不同的结果(因此分组开始)。
伪代码类似于:
1. grouped_data = benchmark.groupby(['field_1'])
2. apply own_function to grouped_data; with inputs ('x', 'y', grouped_data)
3. add back result from function to benchmark as column 'new_field'
谢谢,
改动:
benchmark =
x y z field_1
1 1 3 a
1 2 5 b
9 2 4 a
1 2 5 c
4 6 1 c
阐述:
我还有一个 DataFrame separate_data
,其中包含 x
、
的单独值
separate_data =
x a b c
1 1 3 7
2 2 5 6
3 2 4 4
4 2 5 9
5 6 1 10
需要将其插入到现有的 benchmark
DataFrame 中。 separate_data
中的哪一列应该用于插值 取决于 benchmark
中的 列 field_1
(即上面集合 (a,b,c)
中的值).新列中的内插值基于 benchmark
.
中的 x 值
结果:
基准=
x y z field_1 field_new
1 1 3 a interpolate using separate_data with x=1 and col=a
1 2 5 b interpolate using separate_data with x=1 and col=b
9 2 4 a ... etc
1 2 5 c ...
4 6 1 c ...
有道理吗?
编辑:
我认为你需要先通过 set_index
+ stack
, set index names by rename_axis
重塑 separate_data
并通过重命名设置 Serie
的名称。
然后可以groupby
两个级别并使用一些功能。
然后join
它到benchmark
默认左连接:
separate_data1 =separate_data.set_index('x').stack().rename_axis(('x','field_1')).rename('d')
print (separate_data1)
x field_1
1 a 1
b 3
c 7
2 a 2
b 5
c 6
3 a 2
b 4
c 4
4 a 2
b 5
c 9
5 a 6
b 1
c 10
Name: d, dtype: int64
如果有必要使用一些功能,主要是如果一些 x
和 field_1
成对重复 return 漂亮独特的对:
def func(x):
#sample function
return x / 2 + x ** 2
separate_data1 = separate_data1.groupby(level=['x','field_1']).apply(func)
print (separate_data1)
x field_1
1 a 1.5
b 10.5
c 52.5
2 a 5.0
b 27.5
c 39.0
3 a 5.0
b 18.0
c 18.0
4 a 5.0
b 27.5
c 85.5
5 a 39.0
b 1.5
c 105.0
Name: d, dtype: float64
benchmark = benchmark.join(separate_data1, on=['x','field_1'])
print (benchmark)
x y z field_1 d
0 1 1 3 a 1.5
1 1 2 5 b 10.5
2 9 2 4 a NaN
3 1 2 5 c 52.5
4 4 6 1 c 85.5
我认为你不能使用 transform
因为多列是一起阅读的。
所以使用apply
:
df1 = benchmark.groupby(['field_1']).apply(func)
然后对于新列有多个解决方案,例如使用 join
(默认 left join
)或 map
.
两种方法的示例解决方案是 here。
或者可以使用 flexible apply 可以 return 新 DataFrame
新列。
这是一个工作示例:
# Sample function that sums x and y, then append the field as string.
def func(x, y, z):
return (x + y).astype(str) + z
benchmark['new_field'] = benchmark.groupby('field_1')\
.apply(lambda x: func(x['x'], x['y'], x['field_1']))\
.reset_index(level = 0, drop = True)
结果:
benchmark
Out[139]:
x y z field_1 new_field
0 1 1 3 a 2a
1 1 2 5 b 3b
2 9 2 4 a 11a
3 1 2 5 c 3c
4 4 6 1 c 10c
尝试这样的事情:
groups = benchmark.groupby(benchmark["field_1"])
benchmark = benchmark.join(groups.apply(your_function), on="field_1")
在 your_function 中,您将使用所需的其他列创建新列,例如对它们进行平均、求和等
的文档
在任何地方都找不到这个问题,所以只需在这里试试:
我想做的基本上是使用 groupby 功能和一个自写函数来改变现有的 DataFrame 对象:
benchmark =
x y z field_1
1 1 3 a
1 2 5 b
9 2 4 a
1 2 5 c
4 6 1 c
我想做的是分组 field_1
,应用一个使用特定列作为输入的函数,在本例中是列 x
和 y
,然后加回结果到原始 DataFrame benchmark
作为一个名为 new_field
的新列。函数本身取决于 field_1
中的值,即 field_1=a
与 field_1=b
等相比将产生不同的结果(因此分组开始)。
伪代码类似于:
1. grouped_data = benchmark.groupby(['field_1'])
2. apply own_function to grouped_data; with inputs ('x', 'y', grouped_data)
3. add back result from function to benchmark as column 'new_field'
谢谢,
改动:
benchmark =
x y z field_1
1 1 3 a
1 2 5 b
9 2 4 a
1 2 5 c
4 6 1 c
阐述:
我还有一个 DataFrame separate_data
,其中包含 x
、
separate_data =
x a b c
1 1 3 7
2 2 5 6
3 2 4 4
4 2 5 9
5 6 1 10
需要将其插入到现有的 benchmark
DataFrame 中。 separate_data
中的哪一列应该用于插值 取决于 benchmark
中的 列 field_1
(即上面集合 (a,b,c)
中的值).新列中的内插值基于 benchmark
.
结果:
基准=
x y z field_1 field_new
1 1 3 a interpolate using separate_data with x=1 and col=a
1 2 5 b interpolate using separate_data with x=1 and col=b
9 2 4 a ... etc
1 2 5 c ...
4 6 1 c ...
有道理吗?
编辑:
我认为你需要先通过 set_index
+ stack
, set index names by rename_axis
重塑 separate_data
并通过重命名设置 Serie
的名称。
然后可以groupby
两个级别并使用一些功能。
然后join
它到benchmark
默认左连接:
separate_data1 =separate_data.set_index('x').stack().rename_axis(('x','field_1')).rename('d')
print (separate_data1)
x field_1
1 a 1
b 3
c 7
2 a 2
b 5
c 6
3 a 2
b 4
c 4
4 a 2
b 5
c 9
5 a 6
b 1
c 10
Name: d, dtype: int64
如果有必要使用一些功能,主要是如果一些 x
和 field_1
成对重复 return 漂亮独特的对:
def func(x):
#sample function
return x / 2 + x ** 2
separate_data1 = separate_data1.groupby(level=['x','field_1']).apply(func)
print (separate_data1)
x field_1
1 a 1.5
b 10.5
c 52.5
2 a 5.0
b 27.5
c 39.0
3 a 5.0
b 18.0
c 18.0
4 a 5.0
b 27.5
c 85.5
5 a 39.0
b 1.5
c 105.0
Name: d, dtype: float64
benchmark = benchmark.join(separate_data1, on=['x','field_1'])
print (benchmark)
x y z field_1 d
0 1 1 3 a 1.5
1 1 2 5 b 10.5
2 9 2 4 a NaN
3 1 2 5 c 52.5
4 4 6 1 c 85.5
我认为你不能使用 transform
因为多列是一起阅读的。
所以使用apply
:
df1 = benchmark.groupby(['field_1']).apply(func)
然后对于新列有多个解决方案,例如使用 join
(默认 left join
)或 map
.
两种方法的示例解决方案是 here。
或者可以使用 flexible apply 可以 return 新 DataFrame
新列。
这是一个工作示例:
# Sample function that sums x and y, then append the field as string.
def func(x, y, z):
return (x + y).astype(str) + z
benchmark['new_field'] = benchmark.groupby('field_1')\
.apply(lambda x: func(x['x'], x['y'], x['field_1']))\
.reset_index(level = 0, drop = True)
结果:
benchmark
Out[139]:
x y z field_1 new_field
0 1 1 3 a 2a
1 1 2 5 b 3b
2 9 2 4 a 11a
3 1 2 5 c 3c
4 4 6 1 c 10c
尝试这样的事情:
groups = benchmark.groupby(benchmark["field_1"])
benchmark = benchmark.join(groups.apply(your_function), on="field_1")
在 your_function 中,您将使用所需的其他列创建新列,例如对它们进行平均、求和等
的文档