numpy 在Pandas中进行向量化或加速for循环以进行数据转换

wwwo4jvm  于 2023-08-05  发布在  其他
关注(0)|答案(1)|浏览(106)

我有一个dataframe,格式如下:

  1. df = pd.DataFrame({'Parent_username': ['Bob1', 'Ron23', 'Lisa00', 'Joe_'],
  2. 'Parent_age': [38, None, 40, 26],
  3. 'Child1_name': ['Mike', 'John', 'Curt', 'Kelly'],
  4. 'Child1_age': [2, None, 1, 2],
  5. 'Child2_name': ['Pat', 'Dennis', None, None],
  6. 'Child2_age': [4, None, None, None]})
  7. Parent_username Parent_age Child1_name Child1_age Child2_name Child2_age
  8. 0 Bob1 38.0 Mike 2.0 Pat 4.0
  9. 1 Ron23 NaN John NaN Dennis NaN
  10. 2 Lisa00 40.0 Curt 1.0 None NaN
  11. 3 Joe_ 26.0 Kelly 2.0 None NaN

字符串
正如您在上面看到的,每一行对应一个父级(唯一ID),并且每个父级可以有多个子级。可以有很多孩子,但我列出了2个,每个孩子可以有很多属性,但在这个例子中我只有2个(名字,年龄)。子属性列遵循相同的约定。
我想把它变成这样:

  1. df2 = pd.DataFrame({'Child_name': ['Mike', 'Pat', 'John', 'Dennis', 'Curt', 'Kelly'],
  2. 'Child_number': [1, 2, 1, 2, 1, 1],
  3. 'Child_age': [2, 4, None, None, 1, 2],
  4. 'Parent_username': ['Bob1', 'Bob1', 'Ron23', 'Ron23', 'Lisa00', 'Joe_'],
  5. 'Parent_age': [38, 38, None, None, 40, 26]})
  6. Child_name Child_number Child_age Parent_username Parent_age
  7. 0 Mike 1 2.0 Bob1 38.0
  8. 1 Pat 2 4.0 Bob1 38.0
  9. 2 John 1 NaN Ron23 NaN
  10. 3 Dennis 2 NaN Ron23 NaN
  11. 4 Curt 1 1.0 Lisa00 40.0
  12. 5 Kelly 1 2.0 Joe_ 26.0


每一行对应一个child,Child_number表示它是第一个child还是第二个child,等等。
为了加快速度,我为df 2预先分配了空间,方法是创建一个大小合适的空 Dataframe ,而不是进行连接。我首先通过计算每个父节点有多少个子节点来遍历df 1,以获得df 2所需的行数。
然后,我构建了索引字典,将每个子节点/父节点Map到df 2中的行。我想,既然字典查找很快,这比每次使用where()在df 2中查找行要好。同样,为此使用了for循环。
这些实际上并不需要很长时间。但是,使用for循环将数据从df实际复制到df 2需要很长时间:

  1. for index in df.index:
  2. for col in df.columns:
  3. // copy df.loc[index, col] into the corresponding position in df2 using dataframe.loc


我真的希望有一个更快的方法来做到这一点。我不太了解向量化,也不确定它是否适用于字符串列。
请指示。谢啦,谢啦

r1zhe5dt

r1zhe5dt1#

你的代码很慢,因为你一次处理一个元素。您可以通过一次处理一个列来加快速度。下面的代码查找所有子名称列,查找它们具有值的索引(即不为空),并一次对所有这些字段进行操作。
我还添加了提前列出所有属性的方法,这样您就不必单独手动重命名它们。

  1. cnames = [i for i in df.columns if i.startswith('Child') and i.endswith('name')]
  2. cattrs = ['_name', '_age']
  3. newnames = ['Child' + i for i in cattrs]
  4. dflist = []
  5. for childcol in cnames:
  6. cid = childcol.split('_')[0]
  7. cnum = int(cid[-1])
  8. attrs = [cid + i for i in cattrs] # get all the attributes
  9. attrs.extend(['Parent_username', 'Parent_age'])
  10. cdf = df.loc[df[childcol].dropna().index, attrs]
  11. cdf['Child_number'] = cnum
  12. cdf = cdf.rename(columns=dict(zip(attrs, newnames)))
  13. dflist.append(cdf)
  14. newdf = pd.concat(dflist)
  15. newdf = newdf.reset_index(drop=True)

字符串

展开查看全部

相关问题