pandas - 使用多个分隔符写入文件。慢字符串连接

时间:2016-10-20 11:32:25

标签: python-3.x pandas

我需要编写一个文件,其格式带有基于一系列由点分隔的集合的标签,以及一个用空格分隔的数值。有些集可以是字符串或整数,值可以是整数或浮点数

例如:

a.1.1 0.19

a.1.2 1.23

1.5123.29 0

def write_myfile(df,file):
    cols = df.columns[:-1]
    df2 = pd.DataFrame()
    df2['Labels'] = df[cols].apply(lambda x: '.'.join(x.dropna().astype(str).values.tolist()), axis=1)
    df2['Values'] = df['value']
    df2.to_csv(file,sep = ' ',header=False,index=False)
return dd

所以目前我使用pandas数据帧和第一列中的标签,以及最后一列中的值。它适用于小文件,但效率非常低。我需要编写350万行左右的文件。

有什么建议吗?

1 个答案:

答案 0 :(得分:1)

您可以使用嵌套列表理解,因为需要删除NaN

我认为您在值中有NaN,因为使用dropna

首先将values之后的所有列导出到numpy array,然后导出到list。最后通过构造函数创建新的DataFrame

cols = df.columns[:-1]
a = pd.Series(['.'.join([str(y) for y in x if pd.notnull(y)])
               for x in df[cols].values.tolist()])
b = df['value']

df = pd.DataFrame({'Labels' : a, 'Values' : b})
print (df)
      Labels  Values
0      a.1.1    0.19
1        1.2    1.23
2      a.1.1    0.19
3        1.2    1.23
4  1.5123.29    0.00

<强>计时

(len(df)=5k)

In [280]: %timeit (orig(df))
1 loop, best of 3: 22.2 s per loop

In [281]: %timeit (jez(df1))
10 loops, best of 3: 145 ms per loop

df = pd.DataFrame({
'value': {0: 0.19, 1: 1.23, 2: 0.19, 3: 1.23, 4: 0.0}, 
's': {0: 1, 1: 2, 2: 1, 3: 2, 4: 29}, 
'b': {0: 1, 1: 1, 2: 1, 3: 1, 4: 5123}, 
'a': {0: 'a', 1: np.nan, 2: 'a', 3: np.nan, 4: '1'}})
print (df)

     a     b   s  value
0    a     1   1   0.19
1  NaN     1   2   1.23
2    a     1   1   0.19
3  NaN     1   2   1.23
4    1  5123  29   0.00

df = pd.concat([df]*10000).reset_index(drop=True)

df1 = df.copy()

def orig(df):
    cols = df.columns[:-1]
    df2 = pd.DataFrame()
    df2['Labels'] = df[cols].apply(lambda x: '.'.join(x.dropna().astype(str).values.tolist()), axis=1)
    df2['Values'] = df['value']

    return (df2)


def jez(df): 
    cols = df.columns[:-1]
    a = pd.Series(['.'.join([str(y) for y in x if pd.notnull(y)]) for x in df[cols].values.tolist()])
    b = df['value']
    df = pd.DataFrame({'Labels' : a, 'Values' : b})
    return (df)

print (orig(df))
print (jez(df1))

另一个更有效的解决方案,但它取决于数据是否适合您:

str(y) != 'nan'代替pd.notnull(y)

In [298]: %timeit (jez1(df1))
10 loops, best of 3: 114 ms per loop

def jez1(df): 
    cols = df.columns[:-1]
    a = pd.Series(['.'.join([str(y) for y in x if str(y) != 'nan']) for x in df[cols].values.tolist()])
    b = df['value']
    df = pd.DataFrame({'Labels' : a, 'Values' : b})
    return (df)