问题简介
我在一个DataFrame列中使用字符串编码数据:
id data
0 a 2;0;4208;1;790
1 b 2;0;768;1;47
2 c 2;0;92;1;6
3 d 1;0;341
4 e 3;0;1;2;6;4;132
5 f 3;0;1;1;6;3;492
数据表示系统中某些事件发生的次数。我们可以有256个不同的事件(每个事件都有从0 - 255范围内分配的数字ID)。通常,我们在一个测量周期中只有几个事件发生,存储全零没有意义。这就是为什么数据编码如下:第一个数字表示在测量期间发生了多少事件,然后每对包含event_id和counter。
例如:
"三;零;一;一;六;三;492 "是指:
- 测量期间发生3起事件
- ID = 0的事件发生1次
- ID = 1的事件发生6次
- ID = 3的事件发生492次
- 其他事件没有发生
我需要将数据解码为单独的列。预期结果是DataFrame,如下所示:
id data_0 data_1 data_2 data_3 data_4
0 a 4208.0 790.0 0.0 0.0 0.0
1 b 768.0 47.0 0.0 0.0 0.0
2 c 92.0 6.0 0.0 0.0 0.0
3 d 341.0 0.0 0.0 0.0 0.0
4 e 1.0 0.0 6.0 0.0 132.0
5 f 1.0 6.0 0.0 492.0 0.0
问题本身
我想出了下面的函数来做这件事:
def split_data(data: pd.Series):
tmp = data.str.split(';', expand=True).astype('Int32').fillna(-1)
tmp = tmp.apply(
lambda row: {'{0}_{1}'.format(data.name,row[i*2-1]): row[i*2] for i in range(1,row[0]+1)},
axis='columns',
result_type='expand').fillna(0)
return tmp
df = pd.concat([df, split_data(df.pop('data'))], axis=1)
问题是我有数百万行要处理,这需要很多时间。因为我没有太多的Pandas经验,我希望有人能帮助我更有效地执行这项任务的方式。
编辑-答案分析
好了,我把三个答案都拿出来,并进行了一些基准测试:)。我已经有了一个DataFrame(这很重要!)。正如预期的那样,它们都比我的代码快。例如,对于15行,1000次重复的时间:
- 我的密码:0.5827s
- Schalton代码:0.1138s
- Shubham代码:0.2242s
- SomeDudes的代码:0.2219
看来沙尔顿的密码赢了!
但是...对于1500行,50次重复:
- 我的密码:31.1139
- Schalton代码:2.4599s
- Shubham代码:0.511s
- SomeDudes的代码:17.15
我决定再检查一次,这一次只尝试了一次,但检查了150000行:
- 我的密码:68.6798s
- Schalton代码:6.3889s
- Shubham代码:0.9520s
- SomeDudes的代码:37.8837
有趣的事情发生了:随着DataFrame的大小变大,除了Shubham的版本需要更长的时间!两个最快的版本是Schalton的和Shubham的版本。这是起点问题!我已经有了现有的DataFrame,所以我必须将其转换为字典。字典本身处理真的很快。但是转换需要时间。Shubham的解决方案或多或少与大小无关! Schalton 's对于小数据集非常有效,但是由于转换为dict,对于大数据量它会变慢。另一个比较,这次是150000行,重复30次:
- Schalton代码:170.1538s
- Shubham代码:36.32s
然而,对于具有30000次重复的15行:
- Schalton代码:50.4997s
- Shubham代码:74.0916s
总结
最后,Schalton版本和Shubham版本之间的选择取决于用例:
- 对于大量的小 Dataframe (或在开始时使用字典),使用Schalton的解决方案
- 对于非常大的 Dataframe ,使用Shubham的解决方案。
如上所述,我有大约100万行的数据集,因此我将采用Shubham的答案。
3条答案
按热度按时间wtzytmuj1#
编号
解释
Extract
使用正则表达式模式的所有pairs
旋转
pairs
以调整为所需格式将重新整形的
pairs
Dataframe 与id
列重新连接gwo2fgha2#
我会避免在Pandas中处理这些数据,假设您有其他格式的数据,我会将其解析为字典列表,然后将其加载到Pandas中。
如果你把当前的df作为输入,你可以尝试这样做:
68bkxrlz3#
一个更有效的方法是从
data
构造dict。您观察到拆分字符串中的替代值是如何成为键和值的吗?然后应用
pd.Series
和fillna(0)
以获得包含数据所需的所有列的 Dataframe 。然后你就可以继续了。
代码:
输出:
如果您需要排序列,只需执行以下操作: