将函数应用于Dataframe GroupBy Object并返回数据帧

时间:2015-02-13 04:21:56

标签: python pandas

如何使用Pandas从groupby对象返回数据帧?这里的目的是读取CSV并使用randIP()返回的值替换IP地址列中的每个IP地址。我希望通过分组来保持之后整个混淆数据帧的一致性(每个真实IP映射到新的随机IP)。

我尝试了很多方法,但这似乎是最成功的。 self.df2正在打印为pandas.core.grouby.SeriesGroupBy对象。

def __init__(self, filename):
    self.df = pd.read_csv(filename)
    self.grouped = self.df.groupby('IP Address')
    self.df.reset_index(drop=True, inplace=True)
    for i, k in self.grouped:
        r = randIP()
        k['IP Address'] = k['IP Address'].apply(lambda x: x.replace(x, r))
    self.df2 = self.grouped
    print(self.df2['IP Address'])

1 个答案:

答案 0 :(得分:0)

最好不要尝试从分组操作中修改DataFrame。相反,使用分组操作创建新IP,然后使用map将旧IP映射到新IP,然后(如果需要)将新IP分配回新IP数据帧:

def randomIP():
    return ".".join(str(np.random.randint(0, 255) for it in xrange(4)))

>>> d = pandas.DataFrame({'IP': ['1.2.3.4', '5.6.7.8', '1.2.3.4', '5.6.7.8', '9.10.11.12', '13.14.15.16'], 'Other': ['blah']*6})
>>> d
            IP Other
0      1.2.3.4  blah
1      5.6.7.8  blah
2      1.2.3.4  blah
3      5.6.7.8  blah
4   9.10.11.12  blah
5  13.14.15.16  blah

groupbyapply一起使用会为您提供旧版IP到新版IP的系列映射:

>>> d.groupby('IP').apply(lambda g: randomIP())
IP
1.2.3.4           4.183.193.46
13.14.15.16    186.124.189.188
5.6.7.8          152.24.105.42
9.10.11.12      188.140.91.209

在旧IP列上使用map并传递此新系列会将旧IP映射到新IP:

>>> d.IP.map(d.groupby('IP').apply(lambda g: randomIP()))
0    47.227.125.190
1      164.86.98.48
2    47.227.125.190
3      164.86.98.48
4     44.150.90.127
5     71.111.59.115
Name: IP, dtype: object

如果您想将它们重新分配回DataFrame列,您可以这样做:

>>> d['IP'] = d.IP.map(d.groupby('IP').apply(lambda g: randomIP()))
>>> d
               IP Other
0  238.227.204.61  blah
1   13.201.160.89  blah
2  238.227.204.61  blah
3   13.201.160.89  blah
4    69.33.243.79  blah
5  164.120.13.218  blah

我认为最后一个是您正在寻找的一体化解决方案。 (在这些示例中,随机IP每次都不同,因为我在示例的每个部分再次调用randomIP。)