将函数应用于数据框 GroupBy 对象和 return 数据框
Apply function to Dataframe GroupBy Object and return dataframe
如何使用 Pandas return 来自 groupby 对象的数据框?此处的目的是读入 CSV 并将 IP 地址列中的每个 IP 地址替换为由 randIP() 编辑的值 return。我想通过分组来保持整个混淆数据帧的一致性(每个真实 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'])
最好不要尝试从分组操作内部修改DataFrame。相反,使用分组操作 创建 新 IP,然后使用 map
将旧 IP 映射到新 IP,然后(如果需要)分配新 IP回到 DataFrame:
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
使用 groupby
和 apply
会给你一个从旧 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
。)
如何使用 Pandas return 来自 groupby 对象的数据框?此处的目的是读入 CSV 并将 IP 地址列中的每个 IP 地址替换为由 randIP() 编辑的值 return。我想通过分组来保持整个混淆数据帧的一致性(每个真实 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'])
最好不要尝试从分组操作内部修改DataFrame。相反,使用分组操作 创建 新 IP,然后使用 map
将旧 IP 映射到新 IP,然后(如果需要)分配新 IP回到 DataFrame:
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
使用 groupby
和 apply
会给你一个从旧 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
。)