使用组结果转换pandas DataFrame

时间:2018-05-22 16:13:13

标签: python pandas

嘿我正在寻找一个从DataFrame组中获取结果的pandas解决方案,然后将这些结果应用于完整的数据帧。这是我现在正在做的最小例子,但我发现它不是很好。

New data: a:1:{s:2:"ep";d:5.07333729617E+13;}

给出了这是我正在使用的缩减版本:

import pandas as np
data = [[0.0, 2.4285714285714286, '0', 'mica02', 'd2o'],
         [10.0, 1.4285714285714286, '225', 'mica02', 'd2o'],
         [13.0, 1.0833333333333333, '225', 'mica02', 'd2o'],
         [954.0, 5.420454545454546, '225', 'mica02', 'air'],
         [937.0, 5.162534435261708, '225', 'mica02', 'air'],
         [75.0, 0.4966887417218543, '225', 'mica02', 'h2o'],
         [78.0, 0.49523809523809526, '225', 'mica02', 'h2o'],
        [80.0, 0.49323809523809526, '225', 'mica01', 'h2o'],
       ]
df0 = pd.DataFrame(data, columns=['basesubed', 'normalized', 'rot', 'm0', 'm1'])
df0

现在,按 basesubed normalized rot m0 m1 0 0.0 2.428571 0 mica02 d2o 1 10.0 1.428571 225 mica02 d2o 2 13.0 1.083333 225 mica02 d2o 3 954.0 5.420455 225 mica02 air 4 937.0 5.162534 225 mica02 air 5 75.0 0.496689 225 mica02 h2o 6 78.0 0.495238 225 mica02 h2o 7 80.0 0.493238 225 mica01 h2o m0元数据对DataFrame进行分组,并计算组中的内容。让我们说现在的中位数:

rot

现在我想从原始DataFrame中减去结果,但只有当mask = (df0.m1 == 'h2o') gdf = df0[mask].groupby(['m0', 'rot']).median() gdf basesubed normalized basesubed_n normalized_n m0 rot mica01 225 80.0 0.493238 1.0 1.0 mica02 225 76.5 0.495963 1.0 1.0 的多索引与gdf中的元数据匹配时才会这样做:

df0

我得到了:

for i in range(len(gdf.index.values)):
    mask = ((df0.m0 == gdf.index.values[i][0]) & (df0.rot == gdf.index.values[i][1]))
    df0.loc[mask, 'basesubed_n'] = df0[mask]['basesubed'] / gdf.loc[gdf.index.values[i]].basesubed
    df0.loc[mask, 'normalized_n'] = df0[mask]['normalized'] / gdf.loc[gdf.index.values[i]].normalized
df0

注意第一行是如何得到NaN的,因为它在gdf中没有匹配的条目。这正是我想要的,因为 basesubed normalized rot m0 m1 basesubed_n normalized_n 0 0.0 2.428571 0 mica02 d2o NaN NaN 1 10.0 1.428571 225 mica02 d2o 0.130719 2.880397 2 13.0 1.083333 225 mica02 d2o 0.169935 2.184301 3 954.0 5.420455 225 mica02 air 12.470588 10.929142 4 937.0 5.162534 225 mica02 air 12.248366 10.409103 5 75.0 0.496689 225 mica02 h2o 0.980392 1.001462 6 78.0 0.495238 225 mica02 h2o 1.019608 0.998538 7 80.0 0.493238 225 mica01 h2o 1.000000 1.000000 中没有rot=0m1=h2o。这种不匹配也是为什么我找不到使用df0的解决方案的原因,因为它也与我想要的数据框的形状不匹配。

任何帮助都会被包围。

1 个答案:

答案 0 :(得分:1)

我不了解您要使用的transform方法,但您可以使用merge来阻止循环for。这是一个想法:

# gdf is slightly different, just reset indexes to merge on them later
gdf = df0[mask].groupby(['m0', 'rot']).median().reset_index()
# merge df0 with gdf on the two columns 'm0', 'rot'
df0 = df0.merge(gdf, on = ['m0',  'rot'], how = 'left', suffixes = ('','_median'))
# now you can calculate the column _n such as:
df0['basesubed_n'] = df0['basesubed'] / df0['basesubed_median']
df0['normalized_n'] = df0['normalized'] / df0['normalized_median']
# finally, drop the columns _median
df0 = df0.drop(['basesubed_median','normalized_median'],1)

你得到的输出与你的输出相同

编辑:实际上,我找到了transform的答案,只是这样做:

df0[['basesubed_n','normalized_n']] = df0.groupby(['m0', 'rot'])\
                                         .transform(lambda x: x/x[mask].median())