我需要编写一个文件,其格式带有基于一系列由点分隔的集合的标签,以及一个用空格分隔的数值。有些集可以是字符串或整数,值可以是整数或浮点数
例如:
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万行左右的文件。
有什么建议吗?
答案 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)