我想基于另一列中的值来规范化pandas数据帧的一列中的值。从统计意义上讲,它不是纯粹的规范化。第二个值是一个类型;我想对每种类型的所有第一个值求和,然后在每一行中将值除以该行类型的总和。一个例子应该让这个更清楚。
// Replaces Pointer.
#[derive(Copy, Clone)]
pub struct Object<'a> {
ptr: *mut AtomicUsize,
mark: PhantomData<&'a usize>
}
impl<'a> Object<'a> {
pub fn survive(self); // Now supposed to be perfectly safe!
}
pub type Adjust<'a> = BTreeMap<usize, Object<'a>>;
pub struct Heap { ... }
pub struct Allocator<'a> { ... }
impl Heap {
fn allocator(&'a self) -> Allocator<'a>;
// The following doesn't work:
//
// fn allocate(&'a mut self) -> Object<'a>;
// fn reallocate(&'a mut self, heap: Heap) -> Adjust<'a>;
//
// Because it doesn't allow the user to allocate more
// than one `Object` at a time (!) in a `Heap`.
}
impl<'a> Allocator<'a> {
// Note that the resulting `Object`s are tied to the `Heap`,
// but not to the allocator itself.
fn allocate(&mut self, tag: Tag) -> Object<'a>;
fn reallocate(&mut self, heap: Heap) -> Adjust<'a>;
}
然后我可以用以下内容找到总和:
df = pd.read_table(datafile, names = ["A", "B", "value", "type"])
A B value type
0 A1 B1 1 type1
1 A2 B2 1 type1
2 A1 B1 1 type2
3 A1 B3 1 type3
4 A2 B2 1 type2
5 A2 B4 1 type3
6 A3 B4 1 type2
7 A3 B5 1 type3
8 A4 B6 1 type2
9 A4 B7 1 type3
然后我如何使用它来规范化每一行的值?
我可以使用这样的循环来计算标准化值:
types = df.groupby(["type"])["value"].sum()
type
type1 2
type2 4
type3 4
Name: value, dtype: int64
然后使用具有以下值的新列替换该列:
norms = []
for ix, row in df.iterrows():
norms.append(row["value"]/types[row["type"]])
但据我所知,使用这样的循环效率不高或不合适,并且可能有一种方法可以使用一些标准的pandas函数来实现。
感谢。
答案 0 :(得分:4)
您可以使用transform
,它对每个组执行操作,然后将结果重新展开以匹配原始索引。例如“
>>> df["value"] /= df.groupby("type")["value"].transform(sum)
>>> df
A B value type
0 A1 B1 0.50 type1
1 A2 B2 0.50 type1
2 A1 B1 0.25 type2
3 A1 B3 0.25 type3
4 A2 B2 0.25 type2
5 A2 B4 0.25 type3
6 A3 B4 0.25 type2
7 A3 B5 0.25 type3
8 A4 B6 0.25 type2
9 A4 B7 0.25 type3
因为我们有
>>> df.groupby("type")["value"].transform(sum)
0 2
1 2
2 4
3 4
4 4
5 4
6 4
7 4
8 4
9 4
dtype: int64
答案 1 :(得分:1)
我认为实现此目的的最佳方法是在groupby对象上使用.apply()
方法:
# Using backslashes for explicit line continuation, not seen
# that often in Python but useful in pandas when you're
# chaining a lot of methods one after the other
df['value_normed'] = df.groupby('type', group_keys=False)\
.apply(lambda g: g['value'] / g['value'].sum())
df
Out[9]:
A B value type value_normed
0 A1 B1 1 type1 0.50
1 A2 B2 1 type1 0.50
2 A1 B1 1 type2 0.25
3 A1 B3 1 type3 0.25
4 A2 B2 1 type2 0.25
5 A2 B4 1 type3 0.25
6 A3 B4 1 type2 0.25
7 A3 B5 1 type3 0.25
8 A4 B6 1 type2 0.25
9 A4 B7 1 type3 0.25
您需要group_keys=False
参数,以便type
不会成为每个群组数据的索引,这会阻止您将转换后的值与原始数据帧进行匹配容易。